- add libsrtp back as part of top repo - this repo should be solid

This commit is contained in:
2026-01-31 21:42:23 +03:00
parent 3466156b23
commit 1653877e26
2383 changed files with 55949 additions and 0 deletions

View File

@@ -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

View File

@@ -0,0 +1,44 @@
name: Android CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
strategy:
fail-fast: false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Create Build Environment
run: cmake -E make_directory ${{github.workspace}}/build
- name: Configure CMake
working-directory: ${{github.workspace}}/build
shell: bash
run: cmake $GITHUB_WORKSPACE -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a
- name: Build
working-directory: ${{github.workspace}}/build
shell: bash
run: cmake --build .
- name: Create Build Environment (Shared Library)
run: cmake -E make_directory ${{github.workspace}}/build_shared
- name: Configure CMake (Shared Library)
working-directory: ${{github.workspace}}/build_shared
shell: bash
run: cmake $GITHUB_WORKSPACE -DBUILD_SHARED_LIBS=ON -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a
- name: Build (Shared Library)
working-directory: ${{github.workspace}}/build_shared
shell: bash
run: cmake --build .

View File

@@ -0,0 +1,92 @@
name: AutoTools CI
on:
workflow_dispatch:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
crypto: [internal, openssl, wolfssl, nss]
include:
- crypto: internal
configure-crypto-enable: ""
- crypto: openssl
configure-crypto-enable: "--with-crypto-library=openssl"
- crypto: wolfssl
configure-crypto-enable: "--with-crypto-library=wolfssl"
- crypto: nss
configure-crypto-enable: "--with-crypto-library=nss"
runs-on: ${{ matrix.os }}
steps:
- name: Setup Ubuntu
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install valgrind
- name: Setup Ubuntu wolfSSL
if: matrix.os == 'ubuntu-latest' && matrix.crypto == 'wolfssl'
run: |
git clone https://github.com/wolfSSL/wolfssl
cd wolfssl
git checkout v5.7.0-stable
./autogen.sh
./configure '--enable-srtp-kdf' '--enable-aesctr' '--enable-intelasm' '--enable-aesgcm-stream'
make
sudo make install
sudo ldconfig
cd ..
- name: Setup Ubuntu NSS
if: matrix.os == 'ubuntu-latest' && matrix.crypto == 'nss'
run: sudo apt-get install libnss3-dev
- name: Setup macOS OpenSSL
if: matrix.os == 'macos-latest' && matrix.crypto == 'openssl'
run: echo "configure-env=PKG_CONFIG_PATH=$(brew --prefix openssl@1.1)/lib/pkgconfig" >> $GITHUB_ENV
- name: Setup macOS wolfSSL
if: matrix.os == 'macos-latest' && matrix.crypto == 'wolfssl'
run: |
brew install autoconf automake libtool
git clone https://github.com/wolfSSL/wolfssl
cd wolfssl
git checkout v5.7.0-stable
./autogen.sh
CPU=`sysctl -n machdep.cpu.brand_string`
if [[ "$CPU" =~ Intel ]]; then
./configure '--enable-srtp-kdf' '--enable-aesctr' '--enable-intelasm' '--enable-aesgcm-stream'
else
./configure '--enable-srtp-kdf' '--enable-aesctr' '--enable-armasm' '--enable-aesgcm-stream'
fi
make
sudo make install
cd ..
- name: Setup macOS NSS
if: matrix.os == 'macos-latest' && matrix.crypto == 'nss'
run: brew install nss
- uses: actions/checkout@v2
- name: Configure
run: ${{env.configure-env}} EXTRA_CFLAGS=-Werror ./configure ${{ matrix.configure-crypto-enable}}
- name: Build
run: make
- name: Test
run: make runtest
- name: Test Valgrind
if: matrix.os == 'ubuntu-latest' && matrix.crypto != 'nss'
run: make runtest-valgrind

View File

@@ -0,0 +1,30 @@
name: CIFuzz
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'libsrtp'
language: c++
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'libsrtp'
fuzz-seconds: 300
language: c++
- name: Upload Crash
uses: actions/upload-artifact@v4
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts

View File

@@ -0,0 +1,127 @@
name: CMake CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '20 4 * * 1'
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
crypto: [internal, openssl, openssl3, wolfssl, nss, mbedtls]
exclude:
- os: windows-latest
crypto: openssl
- os: windows-latest
crypto: wolfssl
- os: windows-latest
crypto: openssl3
- os: windows-latest
crypto: nss
- os: windows-latest
crypto: mbedtls
- os: ubuntu-latest
crypto: openssl3
include:
- crypto: internal
cmake-crypto-enable: ""
- crypto: openssl
cmake-crypto-enable: "-DCRYPTO_LIBRARY=openssl"
- crypto: openssl3
cmake-crypto-enable: "-DCRYPTO_LIBRARY=openssl"
- crypto: wolfssl
cmake-crypto-enable: "-DCRYPTO_LIBRARY=wolfssl"
- crypto: nss
cmake-crypto-enable: "-DCRYPTO_LIBRARY=nss"
- crypto: mbedtls
cmake-crypto-enable: "-DCRYPTO_LIBRARY=mbedtls"
runs-on: ${{ matrix.os }}
env:
CTEST_OUTPUT_ON_FAILURE: 1
steps:
- name: Setup Ubuntu wolfSSL
if: matrix.os == 'ubuntu-latest' && matrix.crypto == 'wolfssl'
run: |
git clone https://github.com/wolfSSL/wolfssl
cd wolfssl
git checkout v5.7.0-stable
./autogen.sh
./configure '--enable-srtp-kdf' '--enable-aesctr' '--enable-intelasm' '--enable-aesgcm-stream'
make
sudo make install
cd ..
- name: Setup Ubuntu NSS
if: matrix.os == 'ubuntu-latest' && matrix.crypto == 'nss'
run: |
sudo apt-get update
sudo apt-get install libnss3-dev
- name: Setup Ubuntu MbedTLS
if: matrix.os == 'ubuntu-latest' && matrix.crypto == 'mbedtls'
run: sudo apt-get install libmbedtls-dev
- name: Setup macOS OpenSSL
if: matrix.os == 'macos-latest' && matrix.crypto == 'openssl'
run: echo "cmake-crypto-dir=-DOPENSSL_ROOT_DIR=$(brew --prefix openssl@1.1)" >> $GITHUB_ENV
- name: Setup macOS OpenSSL3
if: matrix.os == 'macos-latest' && matrix.crypto == 'openssl3'
run: |
brew install openssl@3
echo "cmake-crypto-dir=-DOPENSSL_ROOT_DIR=$(brew --prefix openssl@3)" >> $GITHUB_ENV
- name: Setup macOS wolfSSL
if: matrix.os == 'macos-latest' && matrix.crypto == 'wolfssl'
run: |
brew install autoconf automake libtool
git clone https://github.com/wolfSSL/wolfssl
cd wolfssl
git checkout v5.7.0-stable
./autogen.sh
CPU=`sysctl -n machdep.cpu.brand_string`
if [[ "$CPU" =~ Intel ]]; then
./configure '--enable-srtp-kdf' '--enable-aesctr' '--enable-intelasm' '--enable-aesgcm-stream'
else
./configure '--enable-srtp-kdf' '--enable-aesctr' '--enable-armasm' '--enable-aesgcm-stream'
fi
make
sudo make install
cd ..
- name: Setup macOS NSS
if: matrix.os == 'macos-latest' && matrix.crypto == 'nss'
run: brew install nss
- name: Setup macOS MbedTLS
if: matrix.os == 'macos-latest' && matrix.crypto == 'mbedtls'
run: brew install mbedtls
- uses: actions/checkout@v2
- name: Create Build Environment
run: cmake -E make_directory ${{github.workspace}}/build
- name: Configure CMake
working-directory: ${{github.workspace}}/build
shell: bash
run: cmake $GITHUB_WORKSPACE -DLIBSRTP_TEST_APPS=ON ${{ matrix.cmake-crypto-enable}} ${{env.cmake-crypto-dir}}
- name: Build
working-directory: ${{github.workspace}}/build
shell: bash
run: cmake --build .
- name: Test
working-directory: ${{github.workspace}}/build
shell: bash
run: ctest

View File

@@ -0,0 +1,41 @@
name: Start Coverity Scan
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
coverity:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Download Coverity Build Tool
run: |
wget -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=$TOKEN&project=cisco-libSRTP" -O cov-analysis-linux64.tar.gz
mkdir cov-analysis-linux64
tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
- name: Configure
run: ./configure
- name: Build with cov-build
run: |
export PATH=`pwd`/cov-analysis-linux64/bin:$PATH
cov-build --dir cov-int make
- name: Submit the result to Coverity Scan
run: |
tar czvf libsrtp.tgz cov-int
curl \
--form project=cisco-libSRTP \
--form token=$TOKEN \
--form email=pabuhler@cisco.com \
--form file=@libsrtp.tgz \
--form version=2 \
--form description="libSRTP" \
https://scan.coverity.com/builds?project=cisco-libSRTP
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}

View File

@@ -0,0 +1,17 @@
name: Code Formatting Check
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
format-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Clang Format
run: sudo apt install clang-format-14
- name: Run clang format
run: ./format.sh -d

View File

@@ -0,0 +1,24 @@
# This will verify that the fuzzer builds but will not run it
name: Fuzzer build check
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:
jobs:
fuzz:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install clang
run: sudo apt install clang
- name: Configure with fuzzing
run: CC=clang CXX=clang++ CXXFLAGS="-fsanitize=fuzzer-no-link,address,undefined -g -O3" CFLAGS="-fsanitize=fuzzer-no-link,address,undefined -g -O3" LDFLAGS="-fsanitize=fuzzer-no-link,address,undefined" ./configure
- name: Build
run: LIBFUZZER="-fsanitize=fuzzer" make srtp-fuzzer

View File

@@ -0,0 +1,144 @@
name: Meson CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '20 4 * * 1'
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
crypto: [internal, openssl, openssl3, wolfssl, nss, mbedtls]
exclude:
- os: windows-latest
crypto: openssl
- os: windows-latest
crypto: openssl3
- os: windows-latest
crypto: wolfssl
- os: windows-latest
crypto: nss
- os: windows-latest
crypto: mbedtls
- os: ubuntu-latest
crypto: openssl3
include:
- crypto: internal
meson-crypto-enable: ""
- crypto: openssl
meson-crypto-enable: "-Dcrypto-library=openssl"
- crypto: openssl3
meson-crypto-enable: "-Dcrypto-library=openssl"
- crypto: wolfssl
meson-crypto-enable: "-Dcrypto-library=wolfssl"
- crypto: nss
meson-crypto-enable: "-Dcrypto-library=nss"
- crypto: mbedtls
meson-crypto-enable: "-Dcrypto-library=mbedtls"
runs-on: ${{ matrix.os }}
env:
CTEST_OUTPUT_ON_FAILURE: 1
steps:
- name: Setup Ubuntu Meson
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install meson
- name: Setup macOS Meson
if: matrix.os == 'macos-latest'
run: |
brew install meson
- name: Setup Windows Meson & Ninja
if: matrix.os == 'windows-latest'
run: |
choco install ninja
pip3 install meson
- name: Setup Ubuntu wolfSSL
if: matrix.os == 'ubuntu-latest' && matrix.crypto == 'wolfssl'
run: |
git clone https://github.com/wolfSSL/wolfssl
cd wolfssl
git checkout v5.7.0-stable
./autogen.sh
./configure '--enable-srtp-kdf' '--enable-aesctr' '--enable-intelasm' '--enable-aesgcm-stream'
make
sudo make install
cd ..
- name: Setup Ubuntu NSS
if: matrix.os == 'ubuntu-latest' && matrix.crypto == 'nss'
run: |
sudo apt-get update
sudo apt-get install libnss3-dev
- name: Setup Ubuntu MbedTLS
if: matrix.os == 'ubuntu-latest' && matrix.crypto == 'mbedtls'
run: sudo apt-get install libmbedtls-dev
- name: Setup macOS OpenSSL
if: matrix.os == 'macos-latest' && matrix.crypto == 'openssl'
run: echo "pkgconfig-crypto-dir=PKG_CONFIG_PATH=$(brew --prefix openssl@1.1)/lib/pkgconfig" >> $GITHUB_ENV
- name: Setup macOS OpenSSL3
if: matrix.os == 'macos-latest' && matrix.crypto == 'openssl3'
run: |
brew install openssl@3
echo "pkgconfig-crypto-dir=PKG_CONFIG_PATH=$(brew --prefix openssl@3)/lib/pkgconfig" >> $GITHUB_ENV
- name: Setup macOS wolfSSL
if: matrix.os == 'macos-latest' && matrix.crypto == 'wolfssl'
run: |
brew install autoconf automake libtool
git clone https://github.com/wolfSSL/wolfssl
cd wolfssl
git checkout v5.7.0-stable
./autogen.sh
CPU=`sysctl -n machdep.cpu.brand_string`
if [[ "$CPU" =~ Intel ]]; then
./configure '--enable-srtp-kdf' '--enable-aesctr' '--enable-intelasm' '--enable-aesgcm-stream'
else
./configure '--enable-srtp-kdf' '--enable-aesctr' '--enable-armasm' '--enable-aesgcm-stream'
fi
make
sudo make install
cd ..
- name: Setup macOS NSS
if: matrix.os == 'macos-latest' && matrix.crypto == 'nss'
run: brew install nss
- name: Setup macOS MbedTLS
if: matrix.os == 'macos-latest' && matrix.crypto == 'mbedtls'
run: brew install mbedtls
- uses: actions/checkout@v2
- name: Create Build Environment
run: meson setup ${{github.workspace}}/build
- name: Configure Meson
working-directory: ${{github.workspace}}/build
shell: bash
run: ${{ env.pkgconfig-crypto-dir }} meson configure ${{ matrix.meson-crypto-enable }}
- name: Build
working-directory: ${{github.workspace}}/build
shell: bash
run: ninja
- name: Test
working-directory: ${{github.workspace}}/build
shell: bash
run: meson test

View File

@@ -0,0 +1,41 @@
name: Stream List CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
env:
CTEST_OUTPUT_ON_FAILURE: 1
steps:
- uses: actions/checkout@v2
- name: Create Build Environment
run: cmake -E make_directory ${{github.workspace}}/build
- name: Configure CMake
working-directory: ${{github.workspace}}/build
shell: bash
run: cmake $GITHUB_WORKSPACE -DLIBSRTP_TEST_APPS=ON -DCMAKE_C_FLAGS:STRING="-DSRTP_NO_STREAM_LIST -DSRTP_USE_TEST_STREAM_LIST"
- name: Build
working-directory: ${{github.workspace}}/build
shell: bash
run: cmake --build . -t srtp_driver
- name: Test
working-directory: ${{github.workspace}}/build
shell: bash
run: ctest -R srtp_driver

48
src/libs/libsrtp/.gitignore vendored Normal file
View File

@@ -0,0 +1,48 @@
# 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
build*/
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/sha1_driver
crypto/test/stat_driver
tables/aes_tables
test/rdbx_driver
test/replay_driver
test/roc_driver
test/rtp_decoder
test/rtpw
test/srtp_driver
test/test_srtp

377
src/libs/libsrtp/CHANGES Normal file
View File

@@ -0,0 +1,377 @@
Changelog
2.6.0
#667 - remove use of pointers to 32bit values
#666 - Cleaning up cmake and enabled more warnings.
#665 - start using const on internal arguments
#662 - Some srtp_driver fixes
#661 - remove travis reference from README.md
#660 - meson.build: implement mbedtls support
#649 - iv length is constant so set only once
#507 - Add x86 SIMD optimizations to crypto datatypes
#643 - Add a missing typedef for stream list ctx
#641 - cmake: Rename TEST_APPS as LIBSRTP_TEST_APPS option
#640 - cmake: Support configuring as subproject
2.5.0
#636 - Make mbedtls hmac less restrictive in line with RFC and library capabilities
#612 - Allow overriding stream list implementation
#629 - update min openssl version to 1.1.0
#602 - Openssl 3 support for EVP MAC
#628 - Add android build to CI
#616 - add CIFuzz Github action to workflows
#621 - Add policy_set_aes_cm_192_xxx symbols to def file
#617 - Use current directions in stream update test
#614 - Call `set_aad` and `get_tag` in AEAD performance tests
#611 - Create alias for srtp2 as libSRTP::srtp2
#593 - Remove compatibility code for legacy OpenSSL to fix LibreSSL build
#573 - Export CMake Targets
#586 - Avoid initializing local char table when converting nibble to hex
#591 - EVP_CIPHER_CTX_cleanup() is deprecated in OpenSSL 1.1.0
#589 - Correct null cipher key sizes and be more defensive
#570 - Include directory should point to 'include' not to 'include/srtp2'
#551 - Count blocks instead of bytes in AES-ICM limit computation
#561 - Rtp decoder support ssrc and roc
#559 - Use a full-length key even with null ciphers
#558 - Fix set ROC functionality with gcm
2.4.0
Major changes
#529 - Remove EKT files, this was never completed and the draft has since changed.
#512 - Adds support for Mbedtls as a crypto backend.
#503 - Support apple silicon build.
#495 - Adds support for the Meson build system. This is an alternative to Cmake and auto tools.
Other changes
#546 - Improve OpenSSL KDF check.
#542 - Add void to function declarations for EVP_EncryptInit check.
#531 - Remove dead code.
#524 - Support running against nss >= 3.52.
#521 - Remove references to dtls from libsrtp.
#520 - Use nss based hmac when nss enabled.
#519 - Move selftest vectors form backends to common files.
#515 - Extend cmake support.
#514 - Fix gcc11 warning by defining output length.
#502 - Remove visual studio build files.
#501 - cmake: Set the VERSION property of the srtp2 library.
#500 - Fixed issue #499 with buffer overflow.
#498 - Feature/additional error checks.
#496 - Rework check for OPENSSL_cleanse().
#492 - Avoid non-existing compiler flag -O4.
#491 - Fix two-byte RTP header extension encryption.
#478 - Modify cmake to install crypto_types.h instead of cipher_types.h
2.3.0
Major changes
A fuzzer was added to the project based on libFuzzer. This is run as part of Google oss-fuzz, the current status can be found at https://oss-fuzz-build-logs.storage.googleapis.com/index.html#libsrtp . Details available in PR #442 and issue #393.
CMake support was added as an alternative build system. This was primarily added to replace the Visual Studio project files currently checked in but has been extend to support building on all platforms. Initial PR #449 and #455 but has been support has been continuously improved.
NSS support for crypto backend was added. This is can be used as an alternative to openssl. Initial PR #413 but there has been numerous improvements.
Other changes
PR #474 - Add flag to disable pcap dependency when build test apps.
PR #472 - Add ci builds for ios and android.
PR #463 - problem on srtp_aes_icm_openssl_encrypt.
PR #471 - Allow the pcap file to be read from a physical file.
PR #457 - Fix docs crypto_policy_* -> srtp_crypto_policy_* .
PR #452 - crypto/cipher: Reset the EVP_CIPHER_CTX structure before each test.
PR #444 - Extend rtp_ecoder to support RTCP and multiplexed SSRC's.
PR #443 - rtp_decoder avoid crash when no packets found.
PR #429 - Rand for test only.
PR #421 - Fix GCM IV logging.
PR #415 - Fixes unaligned trailer access.
PR #414 - Detect and handle broken "OPENSSL_cleanse".
2.2.0
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
PR #253 - Cipher type cleanup for AES
When libSRTP is compiled with OpenSSL and the AES 256 ICM cipher is used
with RTCP an incorrect initialization vector is formed.
This change will break backwards compatibility with older versions (1.5,
2.0) of libSRTP when using the AES 256 ICM cipher with OpenSSL for RTCP.
PR #259 - Sequence number incorrectly masked for AES GCM IV
The initialization vector for AES GCM encryption was incorrectly formed on
little endian machines.
This change will break backwards compatibility with older versions (1.5,
2.0) of libSRTP when using the AES GCM cipher for RTCP.
PR #287 - Fix OOB read in key generation for encrypted headers with GCM ciphers
Adds padding of GCM salt to the corresponding ICM length used for header
encryption.
This change will break backwards compatibility with version 2.0 of libSRTP
when using the header encryption extension with the AES GCM cipher.
Major changes
PR #204 - OpenSSL performance improvements
Changed key expansion to occur once per key instead of once per packet.
PR #209 - Restore AES-192 under BoringSSL
BoringSSL supports AES-192 and is now enabled in libSRTP.
PR #224 - Master Key Identifiers (MKI) Support patch
Adds MKI support with up to 4 keys.
PR #234 - Report SSRC instead of srtp_stream_t in srtp_event_data_t
srtp_stream_t is an opaque type making the event framework almost useless.
Now the SSRC is returned instead for use as a key in the public API.
PR #238 - Configure changes and improvements
CFLAGS check more shell neutral, quotation fixes, always generate and
install pkg-config file, improved OpenSSL discovery and linking, remove
-fPIC flag on Windows, fix shared library generation under Cygwin, replace
hardcoded CFLAGS with compiler checks, and regenerate configure after
configure.in changes.
PR #241 & PR #261 - Improved logging API to receive log messages from libSRTP
Provides a logging API and the ability to enable logging to stdout and a
file, as well as a switch to enable all internal debug modules.
PR #289 - Added support for set and get the roll-over-counter
Adds an API to set and get the ROC in an (S)RTP session.
PR #304 - Fix (S)RTP and (S)RTCP for big endian machines
The structures srtp_hdr_t, srtcp_hdr_t and srtcp_trailer_t were defined
incorrectly on big endian systems.
Other changes
PR #149 - Don't create a symlink if there is no $(SHAREDLIBVERSION)
PR #151 - Make srtp_driver compile for MIPS
PR #160 - Use PKG_PROG_PKG_CONFIG to find correct pkg-config
PR #167 - Additional RTCP and SRTCP tests
PR #169 - Identified merge conflict created by commit 6b71fb9
PR #173 - Avoid error 'possibly undefined macro: AM_PROG_AR'
PR #174 - Avoid warning 'The macro AC_TRY_LINK is obsolete.'
PR #175 - Remove 2nd -fPIC
PR #182 - Add a length check before reading packet data
PR #191 - On debug, output correct endianness of SSRC
PR #192 - Replace octet_string_is_eq with a constant-time implementation
PR #195 - Add missing __cplusplus header guards
PR #198 - Update sha1_driver.c to avoid memory leaks
PR #202 - Add an explicit cast to avoid a printf format warning on macOS
PR #205 - Update Windows build files to Visual Studio 2015
PR #207 - Fix to install-win.bat syntax, and add installation of x64 libraries
PR #208 - Make replace_cipher and replace_auth public again
PR #211 - Changes for OpenSSL 1.1.0 compatibility
PR #213 - Add cast to `unsigned int` in call to printf in test
PR #214 - Avoid empty initializer braces
PR #222 - Fix issue: No consistency when use some srtp_* functions
PR #231 - Advance version on master in preparation for 2.1 release
PR #232 - Update Travis, do not build with OpenSSL on OSX
PR #233 - crypto/replay/rdbx.c: Return type of srtp_index_guess from int to
int32_t
PR #236 - test/rtp_decoder.c: Removed superfluous conditional
PR #237 - test/rtp_decoder.c: spring cleaning
PR #239 - octet_string_set_to_zero() delegates to OPENSSL_cleanse() if
available, if not it will use srtp_cleanse() to zero memory
PR #243 - EKT is not really supported yet, remove from install
PR #244 - Add simple error checking in timing test to avoid false results
PR #245 - Add missing srtp_cipher_dealloc calls when test fails
PR #246 - test/rtp_decoder: Add missing conditional
PR #248 - New README.md that integrates intro, credits and references from
/doc/ and is used to generate documentation
PR #249 - Remove support for generic aesicm from configure.in
PR #250 - Update README.md, incorrect tag for link
PR #255 - Cleanup outdated comment related to MKI
PR #258 - Add AES-GCM to DTLS-SRTP Protection Profiles
PR #263 - Cleaning up and removing duplicated and outdated code
PR #265 - Introduction of unit test framework: CUTest
PR #267 - crypto/kernel/err.c: Include datatypes.h
PR #272 - Reduce literal constants
PR #273 - SRTP AEAD SRTCP initialization vector regression tests
PR #274 - Update Travis build - add ccache
PR #276 - Reference and docs updates
PR #278 - Removed crypto/test/auth_driver.c and test/lfsr.c
PR #279 - Bump copyright year
PR #283 - Add missing docs in srtp.h
PR #284 - Add strict-prototypes warning if supported
PR #291 - Use const char * for srtp_set_debug_module()
PR #294 - Fix incorrect result of rdb_increment on overflow
PR #300 - Standalone tests
PR #301 - Configure fixes
PR #302 - Fix warning regarding unused variable
PR #303 - Makefile.in: Add gnu as match for shared lib suffix

View File

@@ -0,0 +1,536 @@
cmake_minimum_required(VERSION 3.21)
project(libsrtp3 VERSION 3.0.0 LANGUAGES C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(PACKAGE_VERSION ${PROJECT_VERSION})
set(PACKAGE_STRING "${PROJECT_NAME} ${PROJECT_VERSION}")
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
option(ENABLE_WARNINGS "Enable to add warnings to a target." ON)
option(ENABLE_WARNINGS_AS_ERRORS "Enable to treat warnings as errors." ON)
option(ENABLE_SANITIZE_ADDR "Enable address sanitize." OFF)
option(ENABLE_SANITIZE_UNDEF "Enable undefined sanitize." OFF)
option(ENABLE_SANITIZE_LEAK "Enable leak sanitize (Gcc/Clang only)." OFF)
option(ENABLE_SANITIZE_THREAD "Enable thread sanitize (Gcc/Clang only)." OFF)
option(ENABLE_LTO "Enable to add Link Time Optimization." OFF)
option(LIBSRTP_TEST_APPS "Build libSRTP test applications" ON)
option(BUILD_SHARED_LIBS "Build shared library" OFF)
include(TestBigEndian)
include(CheckIncludeFile)
include(CheckFunctionExists)
include(CheckTypeSize)
include(CheckCSourceCompiles)
include(ConfigSafeGuards)
if(NOT PROJECT_IS_TOP_LEVEL)
set(LIBSRTP_TEST_APPS OFF)
endif()
if(ENABLE_WARNINGS)
include(Warnings)
endif()
test_big_endian(WORDS_BIGENDIAN)
if (NOT APPLE AND CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
set (HAVE_X86 TRUE)
else ()
set (HAVE_X86 FALSE)
endif ()
check_include_file(arpa/inet.h HAVE_ARPA_INET_H)
check_include_file(byteswap.h HAVE_BYTESWAP_H)
check_include_file(inttypes.h HAVE_INTTYPES_H)
check_include_file(machine/types.h HAVE_MACHINE_TYPES_H)
check_include_file(netinet/in.h HAVE_NETINET_IN_H)
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(stdlib.h HAVE_STDLIB_H)
check_include_file(sys/int_types.h HAVE_SYS_INT_TYPES_H)
check_include_file(sys/socket.h HAVE_SYS_SOCKET_H)
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
check_include_file(unistd.h HAVE_UNISTD_H)
check_include_file(windows.h HAVE_WINDOWS_H)
check_include_file(winsock2.h HAVE_WINSOCK2_H)
check_function_exists(sigaction HAVE_SIGACTION)
check_function_exists(inet_aton HAVE_INET_ATON)
check_function_exists(inet_pton HAVE_INET_PTON)
check_function_exists(usleep HAVE_USLEEP)
check_type_size(uint8_t UINT8_T)
check_type_size(uint16_t UINT16_T)
check_type_size(uint32_t UINT32_T)
check_type_size(uint64_t UINT64_T)
check_type_size(int32_t INT32_T)
check_type_size("unsigned long" SIZEOF_UNSIGNED_LONG)
check_type_size("unsigned long long" SIZEOF_UNSIGNED_LONG_LONG)
check_c_source_compiles("inline void func(); void func() { } int main() { func(); return 0; }" HAVE_INLINE)
if(NOT HAVE_INLINE)
check_c_source_compiles("__inline void func(); void func() { } int main() { func(); return 0; }" HAVE___INLINE)
endif()
set(ENABLE_DEBUG_LOGGING OFF CACHE BOOL "Enable debug logging in all modules")
set(ERR_REPORTING_STDOUT OFF CACHE BOOL "Enable logging to stdout")
set(ERR_REPORTING_FILE "" CACHE FILEPATH "Use file for logging")
set(CRYPTO_LIBRARY_VALUES "internal;openssl;wolfssl;mbedtls;nss")
set(CRYPTO_LIBRARY "internal" CACHE STRING
"Crypto library used by libSRTP, can be one of: ${CRYPTO_LIBRARY_VALUES}")
set_property(CACHE CRYPTO_LIBRARY PROPERTY STRINGS ${CRYPTO_LIBRARY_VALUES})
if(NOT CRYPTO_LIBRARY IN_LIST CRYPTO_LIBRARY_VALUES)
message(FATAL_ERROR "Invalid value for CRYPTO_LIBRARY: ${CRYPTO_LIBRARY}. Allowed values are: ${CRYPTO_LIBRARY_VALUES}")
endif()
message(STATUS "Using crypto library: ${CRYPTO_LIBRARY}")
set(USE_EXTERNAL_CRYPTO TRUE)
set(ENABLE_OPENSSL FALSE)
set(ENABLE_WOLFSSL FALSE)
set(ENABLE_MBEDTLS FALSE)
set(ENABLE_NSS FALSE)
if(CRYPTO_LIBRARY STREQUAL "internal")
set(USE_EXTERNAL_CRYPTO FALSE)
elseif(CRYPTO_LIBRARY STREQUAL "openssl")
set(ENABLE_OPENSSL TRUE)
find_package(OpenSSL REQUIRED)
set(OPENSSL ${ENABLE_OPENSSL} CACHE BOOL INTERNAL)
set(GCM ${ENABLE_OPENSSL} CACHE BOOL INTERNAL)
elseif(CRYPTO_LIBRARY STREQUAL "wolfssl")
set(ENABLE_WOLFSSL TRUE)
find_package(wolfSSL REQUIRED)
set(WOLFSSL ${ENABLE_WOLFSSL} CACHE BOOL INTERNAL)
set(WOLFSSL_KDF ${ENABLE_WOLFSSL} CACHE BOOL INTERNAL)
set(GCM ${ENABLE_WOLFSSL} CACHE BOOL INTERNAL)
elseif(CRYPTO_LIBRARY STREQUAL "mbedtls")
set(ENABLE_MBEDTLS TRUE)
find_package(MbedTLS REQUIRED)
set(MBEDTLS ${ENABLE_MBEDTLS} CACHE BOOL INTERNAL)
set(GCM ${ENABLE_MBEDTLS} CACHE BOOL INTERNAL)
elseif(CRYPTO_LIBRARY STREQUAL "nss")
set(ENABLE_NSS TRUE)
find_package(NSS REQUIRED)
set(NSS ${ENABLE_NSS} CACHE BOOL INTERNAL)
set(GCM ${ENABLE_NSS} CACHE BOOL INTERNAL)
endif()
set(CONFIG_FILE_DIR ${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CONFIG_FILE_DIR})
configure_file(config_in_cmake.h ${CONFIG_FILE_DIR}/config.h)
add_definitions(-DHAVE_CONFIG_H)
if(ENABLE_SANITIZE_ADDR OR ENABLE_SANITIZE_UNDEF)
include(Sanitizer)
add_sanitizer_flags()
endif()
if(ENABLE_LTO)
include(LTO)
endif()
set(SOURCES_C
srtp/srtp.c
)
set(CIPHERS_SOURCES_C
crypto/cipher/cipher.c
crypto/cipher/cipher_test_cases.c
crypto/cipher/cipher_test_cases.h
crypto/cipher/null_cipher.c
)
if(ENABLE_OPENSSL)
list(APPEND CIPHERS_SOURCES_C
crypto/cipher/aes_icm_ossl.c
crypto/cipher/aes_gcm_ossl.c
)
elseif(ENABLE_WOLFSSL)
list(APPEND CIPHERS_SOURCES_C
crypto/cipher/aes_icm_wssl.c
crypto/cipher/aes_gcm_wssl.c
)
elseif(ENABLE_MBEDTLS)
list(APPEND CIPHERS_SOURCES_C
crypto/cipher/aes_icm_mbedtls.c
crypto/cipher/aes_gcm_mbedtls.c
)
elseif(ENABLE_NSS)
list(APPEND CIPHERS_SOURCES_C
crypto/cipher/aes_icm_nss.c
crypto/cipher/aes_gcm_nss.c
)
else()
list(APPEND CIPHERS_SOURCES_C
crypto/cipher/aes.c
crypto/cipher/aes_icm.c
)
endif()
set(HASHES_SOURCES_C
crypto/hash/auth.c
crypto/hash/auth_test_cases.c
crypto/hash/auth_test_cases.h
crypto/hash/null_auth.c
)
if(ENABLE_OPENSSL)
list(APPEND HASHES_SOURCES_C
crypto/hash/hmac_ossl.c
)
elseif(ENABLE_WOLFSSL)
list(APPEND HASHES_SOURCES_C
crypto/hash/hmac_wssl.c
)
elseif(ENABLE_MBEDTLS)
list(APPEND HASHES_SOURCES_C
crypto/hash/hmac_mbedtls.c
)
elseif(ENABLE_NSS)
list(APPEND HASHES_SOURCES_C
crypto/hash/hmac_nss.c
)
else()
list(APPEND HASHES_SOURCES_C
crypto/hash/hmac.c
crypto/hash/sha1.c
)
endif()
set(KERNEL_SOURCES_C
crypto/kernel/alloc.c
crypto/kernel/crypto_kernel.c
crypto/kernel/err.c
crypto/kernel/key.c
)
set(MATH_SOURCES_C
crypto/math/datatypes.c
)
set(REPLAY_SOURCES_C
crypto/replay/rdb.c
crypto/replay/rdbx.c
)
set(SOURCES_H
crypto/include/aes.h
crypto/include/aes_icm.h
crypto/include/alloc.h
crypto/include/auth.h
crypto/include/cipher.h
crypto/include/cipher_types.h
crypto/include/crypto_kernel.h
crypto/include/crypto_types.h
crypto/include/datatypes.h
crypto/include/err.h
crypto/include/hmac.h
crypto/include/key.h
crypto/include/null_auth.h
crypto/include/null_cipher.h
crypto/include/rdb.h
crypto/include/rdbx.h
crypto/include/sha1.h
include/srtp.h
include/srtp_priv.h
${CONFIG_FILE_DIR}/config.h
)
if(BUILD_SHARED_LIBS AND WIN32)
list(APPEND SOURCES_C
srtp.def
)
endif()
source_group("src" FILES ${SOURCES_C})
source_group("src\\Ciphers" FILES ${CIPHERS_SOURCES_C})
source_group("src\\Hashes" FILES ${HASHES_SOURCES_C})
source_group("src\\Kernel" FILES ${KERNEL_SOURCES_C})
source_group("src\\Math" FILES ${MATH_SOURCES_C})
source_group("src\\Replay" FILES ${REPLAY_SOURCES_C})
source_group("include" FILES ${SOURCES_H})
add_library(srtp3
${SOURCES_C}
${CIPHERS_SOURCES_C}
${HASHES_SOURCES_C}
${KERNEL_SOURCES_C}
${MATH_SOURCES_C}
${REPLAY_SOURCES_C}
${SOURCES_H}
)
add_library(libSRTP::srtp3 ALIAS srtp3)
if (${ENABLE_WARNINGS})
target_set_warnings(
TARGET
"srtp3"
ENABLE
${ENABLE_WARNINGS}
AS_ERRORS
${ENABLE_WARNINGS_AS_ERRORS})
endif()
if(${ENABLE_LTO})
target_enable_lto(
TARGET
"srtp3"
ENABLE
ON)
endif()
set_target_properties(srtp3 PROPERTIES VERSION 1)
target_include_directories(srtp3 PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/crypto/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
if(ENABLE_OPENSSL)
target_include_directories(srtp3 PRIVATE ${OPENSSL_INCLUDE_DIR})
target_link_libraries(srtp3 OpenSSL::Crypto)
elseif(ENABLE_WOLFSSL)
target_include_directories(srtp3 PRIVATE ${WOLFSSL_INCLUDE_DIR})
target_link_libraries(srtp3 ${WOLFSSL_LIBRARY})
elseif(ENABLE_MBEDTLS)
target_include_directories(srtp3 PRIVATE ${MBEDTLS_INCLUDE_DIRS})
target_link_libraries(srtp3 ${MBEDTLS_LIBRARIES})
elseif(ENABLE_NSS)
target_include_directories(srtp3 PRIVATE ${NSS_INCLUDE_DIRS})
target_link_libraries(srtp3 ${NSS_LIBRARIES})
endif()
if(WIN32)
target_link_libraries(srtp3 ws2_32)
target_compile_definitions(srtp3 PUBLIC _CRT_SECURE_NO_WARNINGS)
endif()
install(TARGETS srtp3 DESTINATION lib
EXPORT libSRTPTargets
)
install(FILES include/srtp.h crypto/include/auth.h
crypto/include/cipher.h
crypto/include/crypto_types.h
DESTINATION include/srtp3)
if(LIBSRTP_TEST_APPS)
enable_testing()
find_package(PCAP)
if (PCAP_FOUND)
add_executable(rtp_decoder test/rtp_decoder.c test/getopt_s.c test/util.c)
target_link_libraries(rtp_decoder srtp3 ${PCAP_LIBRARY})
endif()
if(NOT (BUILD_SHARED_LIBS AND WIN32))
if(NOT USE_EXTERNAL_CRYPTO)
add_executable(aes_calc crypto/test/aes_calc.c test/getopt_s.c test/util.c)
target_include_directories(aes_calc PRIVATE test)
target_link_libraries(aes_calc srtp3)
target_set_warnings(
TARGET
aes_calc
ENABLE
${ENABLE_WARNINGS}
AS_ERRORS
${ENABLE_WARNINGS_AS_ERRORS})
add_test(aes_calc_128 aes_calc 000102030405060708090a0b0c0d0e0f
00112233445566778899aabbccddeeff
69c4e0d86a7b0430d8cdb78070b4c55a)
add_test(aes_calc_256 aes_calc 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
00112233445566778899aabbccddeeff
8ea2b7ca516745bfeafc49904b496089)
add_executable(sha1_driver crypto/test/sha1_driver.c test/util.c)
target_set_warnings(
TARGET
sha1_driver
ENABLE
${ENABLE_WARNINGS}
AS_ERRORS
${ENABLE_WARNINGS_AS_ERRORS})
target_include_directories(sha1_driver PRIVATE test)
target_link_libraries(sha1_driver srtp3)
add_test(sha1_driver sha1_driver -v)
endif()
add_executable(datatypes_driver crypto/test/datatypes_driver.c test/util.c)
target_set_warnings(
TARGET
datatypes_driver
ENABLE
${ENABLE_WARNINGS}
AS_ERRORS
${ENABLE_WARNINGS_AS_ERRORS})
target_include_directories(datatypes_driver PRIVATE test)
target_link_libraries(datatypes_driver srtp3)
add_test(datatypes_driver datatypes_driver -v)
add_executable(cipher_driver crypto/test/cipher_driver.c test/getopt_s.c test/util.c)
target_set_warnings(
TARGET
cipher_driver
ENABLE
${ENABLE_WARNINGS}
AS_ERRORS
${ENABLE_WARNINGS_AS_ERRORS})
target_include_directories(cipher_driver PRIVATE test)
target_link_libraries(cipher_driver srtp3)
add_test(cipher_driver cipher_driver -v)
add_executable(kernel_driver crypto/test/kernel_driver.c test/getopt_s.c)
target_set_warnings(
TARGET
kernel_driver
ENABLE
${ENABLE_WARNINGS}
AS_ERRORS
${ENABLE_WARNINGS_AS_ERRORS})
target_include_directories(kernel_driver PRIVATE test)
target_link_libraries(kernel_driver srtp3)
add_test(kernel_driver kernel_driver -v)
add_executable(rdbx_driver test/rdbx_driver.c test/getopt_s.c test/ut_sim.c)
target_set_warnings(
TARGET
rdbx_driver
ENABLE
${ENABLE_WARNINGS}
AS_ERRORS
${ENABLE_WARNINGS_AS_ERRORS})
target_include_directories(rdbx_driver PRIVATE test)
target_link_libraries(rdbx_driver srtp3)
add_test(rdbx_driver rdbx_driver -v)
add_executable(replay_driver test/replay_driver.c test/ut_sim.c)
target_set_warnings(
TARGET
replay_driver
ENABLE
${ENABLE_WARNINGS}
AS_ERRORS
${ENABLE_WARNINGS_AS_ERRORS})
target_include_directories(replay_driver PRIVATE test)
target_link_libraries(replay_driver srtp3)
add_test(replay_driver replay_driver -v)
add_executable(roc_driver test/roc_driver.c test/ut_sim.c)
target_set_warnings(
TARGET
roc_driver
ENABLE
${ENABLE_WARNINGS}
AS_ERRORS
${ENABLE_WARNINGS_AS_ERRORS})
target_include_directories(roc_driver PRIVATE test)
target_link_libraries(roc_driver srtp3)
add_test(roc_driver roc_driver -v)
endif()
add_executable(srtp_driver test/srtp_driver.c
test/util.c test/getopt_s.c)
target_set_warnings(
TARGET
srtp_driver
ENABLE
${ENABLE_WARNINGS}
AS_ERRORS
${ENABLE_WARNINGS_AS_ERRORS})
target_link_libraries(srtp_driver srtp3)
add_test(srtp_driver srtp_driver -v)
add_test(srtp_driver_not_in_place_io srtp_driver -v -n)
if(NOT (BUILD_SHARED_LIBS AND WIN32))
add_executable(test_srtp test/test_srtp.c)
target_set_warnings(
TARGET
test_srtp
ENABLE
${ENABLE_WARNINGS}
AS_ERRORS
${ENABLE_WARNINGS_AS_ERRORS})
if(ENABLE_OPENSSL)
target_include_directories(test_srtp PRIVATE ${OPENSSL_INCLUDE_DIR})
elseif(ENABLE_WOLFSSL)
target_include_directories(test_srtp PRIVATE ${WOLFSSL_INCLUDE_DIR})
elseif(ENABLE_MBEDTLS)
target_include_directories(test_srtp PRIVATE ${MBEDTLS_INCLUDE_DIRS})
elseif(ENABLE_NSS)
target_include_directories(test_srtp PRIVATE ${NSS_INCLUDE_DIRS})
endif()
target_link_libraries(test_srtp srtp3)
add_test(test_srtp test_srtp)
endif()
find_program(BASH_PROGRAM bash)
if(BASH_PROGRAM AND NOT WIN32)
add_executable(rtpw test/rtpw.c test/rtp.c test/util.c test/getopt_s.c)
target_set_warnings(
TARGET
rtpw
ENABLE
${ENABLE_WARNINGS}
AS_ERRORS
${ENABLE_WARNINGS_AS_ERRORS})
target_link_libraries(rtpw srtp3)
add_test(NAME rtpw_test
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test/rtpw_test.sh -w ${CMAKE_CURRENT_SOURCE_DIR}/test/words.txt
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
if(GCM)
add_test(NAME rtpw_test_gcm
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/test/rtpw_test_gcm.sh -w ${CMAKE_CURRENT_SOURCE_DIR}/test/words.txt
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
endif()
endif()
endif()
# Export targets
install(
EXPORT libSRTPTargets
FILE libSRTPTargets.cmake
NAMESPACE libSRTP::
DESTINATION lib/cmake/libSRTP
)
#--------------------------------------------------------------------
# Create generated files
#--------------------------------------------------------------------
include(CMakePackageConfigHelpers)
# Generate the config file that is includes the exports
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/libSRTPConfig.cmake"
INSTALL_DESTINATION "${CONFIG_FILE_DIR}"
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
# Generate the version file for the config file
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/libSRTPConfigVersion.cmake"
VERSION "${PROJECT_VERSION}"
COMPATIBILITY AnyNewerVersion
)
#--------------------------------------------------------------------
# Install CMake config files
#--------------------------------------------------------------------
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/libSRTPConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/libSRTPConfigVersion.cmake
DESTINATION lib/cmake/libSRTP
)

View File

@@ -0,0 +1,3 @@
# Meson build file maintainers
meson.build @nirbheek @tp-m @xhaakon
meson_options.txt @nirbheek @tp-m @xhaakon

View File

@@ -0,0 +1,3 @@
@PACKAGE_INIT@
include ( "${CMAKE_CURRENT_LIST_DIR}/libSRTPTargets.cmake" )

35
src/libs/libsrtp/LICENSE Normal file
View File

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

View File

@@ -0,0 +1,346 @@
# Makefile for secure rtp
#
# David A. McGrew
# Cisco Systems, Inc.
# targets:
#
# runtest runs test applications
# runtest-valgrind runs test applications with valgrind
# test builds test applications
# libsrtp3.a static library implementing srtp
# libsrtp3.so shared library implementing srtp
# clean removes objects, libs, and executables
# distribution cleans and builds a .tgz
# tags builds etags file from all .c and .h files
DYNAMIC_PATH_VAR = @DYNAMIC_PATH_VAR@
CRYPTO_LIBDIR = @CRYPTO_LIBDIR@
USE_EXTERNAL_CRYPTO = @USE_EXTERNAL_CRYPTO@
HAVE_PCAP = @HAVE_PCAP@
# Specify how tests should find shared libraries on macOS and Linux
#
# macOS purges DYLD_LIBRARY_PATH when spawning subprocesses, so it's
# not possible to pass this in from the outside; we have to specify
# it for any subprocesses we call. No support for dynamic linked
# tests on Windows.
ifneq ($(strip $(CRYPTO_LIBDIR)),)
ifneq ($(OS),Windows_NT)
UNAME_S = $(shell uname -s)
ifeq ($(UNAME_S),Linux)
FIND_LIBRARIES = LD_LIBRARY_PATH=$(CRYPTO_LIBDIR)
endif
ifeq ($(UNAME_S),Darwin)
FIND_LIBRARIES = DYLD_LIBRARY_PATH=$(CRYPTO_LIBDIR)
endif
CRYPTO_LIBDIR_FORWARD = CRYPTO_LIBDIR=$(CRYPTO_LIBDIR)
endif
endif
.PHONY: all shared_library test
all: test
runtest: test
@echo "running libsrtp3 test applications..."
$(FIND_LIBRARIES) crypto/test/cipher_driver$(EXE) -v >/dev/null
$(FIND_LIBRARIES) crypto/test/kernel_driver$(EXE) -v >/dev/null
$(FIND_LIBRARIES) test/test_srtp$(EXE) >/dev/null
$(FIND_LIBRARIES) test/rdbx_driver$(EXE) -v >/dev/null
$(FIND_LIBRARIES) test/srtp_driver$(EXE) -v >/dev/null
$(FIND_LIBRARIES) test/roc_driver$(EXE) -v >/dev/null
$(FIND_LIBRARIES) test/replay_driver$(EXE) -v >/dev/null
cd test; $(CRYPTO_LIBDIR_FORWARD) $(abspath $(srcdir))/test/rtpw_test.sh -w $(abspath $(srcdir))/test/words.txt >/dev/null
ifeq (1, $(USE_EXTERNAL_CRYPTO))
cd test; $(CRYPTO_LIBDIR_FORWARD) $(abspath $(srcdir))/test/rtpw_test_gcm.sh -w $(abspath $(srcdir))/test/words.txt >/dev/null
endif
@echo "libsrtp3 test applications passed."
$(MAKE) -C crypto runtest
runtest-valgrind: test
@echo "running libsrtp3 test applications... (valgrind)"
valgrind --error-exitcode=1 --leak-check=full --suppressions=./valgrind.supp test/test_srtp$(EXE) -v >/dev/null
valgrind --error-exitcode=1 --leak-check=full --suppressions=./valgrind.supp test/srtp_driver$(EXE) -v >/dev/null
@echo "libsrtp3 test applications passed. (valgrind)"
# makefile variables
CC = @CC@
CXX = @CXX@
INCDIR = -Icrypto/include -I$(srcdir)/include -I$(srcdir)/crypto/include
DEFS = @DEFS@
CPPFLAGS= @CPPFLAGS@
CFLAGS = @CFLAGS@
CXXFLAGS= @CXXFLAGS@
srtp-fuzzer: CFLAGS += -g
srtp-fuzzer: CXXFLAGS += -g
LIBS = @LIBS@
LDFLAGS = -L. @LDFLAGS@
COMPILE = $(CC) $(DEFS) $(INCDIR) $(CPPFLAGS) $(CFLAGS)
SRTPLIB = -lsrtp3
PCAP_LIB = @PCAP_LIB@
AR = @AR@
RANLIB = @RANLIB@
INSTALL = @INSTALL@
# EXE defines the suffix on executables - it's .exe for Windows, and
# null on linux, bsd, and OS X and other OSes.
EXE = @EXE@
HMAC_OBJS = @HMAC_OBJS@
AES_ICM_OBJS = @AES_ICM_OBJS@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
includedir = @includedir@
libdir = @libdir@
bindir = @bindir@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libsrtp3.pc
SHAREDLIBVERSION = 1
ifneq (,$(or $(findstring linux,@host@), $(findstring gnu,@host@)))
SHAREDLIB_DIR = $(libdir)
SHAREDLIB_LDFLAGS = -shared -Wl,-soname,$@
SHAREDLIBSUFFIXNOVER = so
SHAREDLIBSUFFIX = $(SHAREDLIBSUFFIXNOVER).$(SHAREDLIBVERSION)
else ifneq (,$(or $(findstring cygwin,@host@), $(findstring mingw,@host@)))
SHAREDLIB_DIR = $(bindir)
SHAREDLIB_LDFLAGS = -shared -Wl,--out-implib,libsrtp3.dll.a
SHAREDLIBVERSION =
SHAREDLIBSUFFIXNOVER = dll
SHAREDLIBSUFFIX = $(SHAREDLIBSUFFIXNOVER)
else ifeq (darwin,$(findstring darwin,@host@))
SHAREDLIB_DIR = $(libdir)
SHAREDLIB_LDFLAGS = -dynamiclib -twolevel_namespace \
-fno-common -headerpad_max_install_names -install_name $(libdir)/$@
SHAREDLIBSUFFIXNOVER = dylib
SHAREDLIBSUFFIX = $(SHAREDLIBVERSION).$(SHAREDLIBSUFFIXNOVER)
endif
# implicit rules for object files and test apps
%.o: %.c
$(COMPILE) -c $< -o $@
%$(EXE): %.c
$(COMPILE) $(LDFLAGS) $< -o $@ $(SRTPLIB) $(LIBS)
ciphers = crypto/cipher/cipher.o crypto/cipher/null_cipher.o \
crypto/cipher/cipher_test_cases.o \
$(AES_ICM_OBJS)
hashes = crypto/hash/null_auth.o crypto/hash/auth.o \
crypto/hash/auth_test_cases.o \
$(HMAC_OBJS)
replay = crypto/replay/rdb.o crypto/replay/rdbx.o
math = crypto/math/datatypes.o
ust = crypto/ust/ust.o
err = crypto/kernel/err.o
kernel = crypto/kernel/crypto_kernel.o crypto/kernel/alloc.o \
crypto/kernel/key.o $(err) # $(ust)
cryptobj = $(ciphers) $(hashes) $(math) $(kernel) $(replay)
# libsrtp3.a (implements srtp processing)
srtpobj = srtp/srtp.o
libsrtp3.a: $(srtpobj) $(cryptobj) $(gdoi)
$(AR) cr libsrtp3.a $^
$(RANLIB) libsrtp3.a
libsrtp3.$(SHAREDLIBSUFFIX): $(srtpobj) $(cryptobj) $(gdoi)
$(CC) -shared -o $@ $(SHAREDLIB_LDFLAGS) \
$^ $(LDFLAGS) $(LIBS)
if [ -n "$(SHAREDLIBVERSION)" ]; then \
ln -sfn $@ libsrtp3.$(SHAREDLIBSUFFIXNOVER); \
fi
shared_library: libsrtp3.$(SHAREDLIBSUFFIX)
libsrtp3.so: $(srtpobj) $(cryptobj)
$(CC) -shared -Wl,-soname,libsrtp3.so \
-o libsrtp3.so $^ $(LDFLAGS)
# test applications
ifneq (1, $(USE_EXTERNAL_CRYPTO))
AES_CALC = crypto/test/aes_calc$(EXE)
SHA1_DRIVER = crypto/test/sha1_driver$(EXE)
endif
crypto_testapp = $(AES_CALC) crypto/test/cipher_driver$(EXE) \
crypto/test/datatypes_driver$(EXE) crypto/test/kernel_driver$(EXE) \
$(SHA1_DRIVER) crypto/test/env$(EXE)
testapp = $(crypto_testapp) test/srtp_driver$(EXE) test/replay_driver$(EXE) \
test/roc_driver$(EXE) test/rdbx_driver$(EXE) test/rtpw$(EXE) \
test/test_srtp$(EXE)
ifeq (1, $(HAVE_PCAP))
testapp += test/rtp_decoder$(EXE)
endif
$(testapp): libsrtp3.a
test/rtpw$(EXE): test/rtpw.c test/rtp.c test/util.c test/getopt_s.c \
crypto/math/datatypes.c
$(COMPILE) $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
ifeq (1, $(HAVE_PCAP))
test/rtp_decoder$(EXE): test/rtp_decoder.c test/rtp.c test/util.c test/getopt_s.c \
crypto/math/datatypes.c
$(COMPILE) $(LDFLAGS) -o $@ $^ $(PCAP_LIB) $(LIBS) $(SRTPLIB)
endif
crypto/test/aes_calc$(EXE): crypto/test/aes_calc.c test/util.c
$(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
test/test_srtp$(EXE): test/test_srtp.c
$(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
crypto/test/datatypes_driver$(EXE): crypto/test/datatypes_driver.c test/util.c
$(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
crypto/test/sha1_driver$(EXE): crypto/test/sha1_driver.c test/util.c
$(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
test/srtp_driver$(EXE): test/srtp_driver.c test/util.c test/getopt_s.c
$(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
test/rdbx_driver$(EXE): test/rdbx_driver.c test/getopt_s.c test/ut_sim.c
$(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
test/roc_driver$(EXE): test/roc_driver.c test/ut_sim.c
$(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
test/replay_driver$(EXE): test/replay_driver.c test/ut_sim.c
$(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
crypto/test/cipher_driver$(EXE): crypto/test/cipher_driver.c test/getopt_s.c test/util.c
$(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
crypto/test/kernel_driver$(EXE): crypto/test/kernel_driver.c test/getopt_s.c
$(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
crypto/test/env$(EXE): crypto/test/env.c test/getopt_s.c
$(COMPILE) -I$(srcdir)/test $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB)
test: $(testapp)
@echo "Build done. Please run '$(MAKE) runtest' to run self tests."
memtest: test/srtp_driver
@test/srtp_driver -v -d "alloc" > tmp
@grep freed tmp | wc -l > freed
@grep allocated tmp | wc -l > allocated
@echo "checking for memory leaks (only works with --enable-stdout)"
cmp -s allocated freed
@echo "passed (same number of alloc() and dealloc() calls found)"
@rm freed allocated tmp
# the target 'plot' runs the timing test (test/srtp_driver -t) then
# uses gnuplot to produce plots of the results - see the script file
# 'timing'
plot: test/srtp_driver
test/srtp_driver -t > timing.dat
# bookkeeping: tags, clean, and distribution
tags:
etags */*.[ch] */*/*.[ch]
# documentation - the target libsrtp3doc builds html documentation
libsrtp3doc:
$(MAKE) -C doc
# fuzzer
srtp-fuzzer: libsrtp3.a
$(MAKE) -C fuzzer
.PHONY: clean superclean distclean install
install:
$(INSTALL) -d $(DESTDIR)$(includedir)/srtp3
$(INSTALL) -d $(DESTDIR)$(libdir)
cp $(srcdir)/include/srtp.h $(DESTDIR)$(includedir)/srtp3
cp $(srcdir)/crypto/include/cipher.h $(DESTDIR)$(includedir)/srtp3
cp $(srcdir)/crypto/include/auth.h $(DESTDIR)$(includedir)/srtp3
cp $(srcdir)/crypto/include/crypto_types.h $(DESTDIR)$(includedir)/srtp3
if [ -f libsrtp3.a ]; then cp libsrtp3.a $(DESTDIR)$(libdir)/; fi
if [ -f libsrtp3.dll.a ]; then cp libsrtp3.dll.a $(DESTDIR)$(libdir)/; fi
if [ -f libsrtp3.$(SHAREDLIBSUFFIX) ]; then \
$(INSTALL) -d $(DESTDIR)$(SHAREDLIB_DIR); \
cp libsrtp3.$(SHAREDLIBSUFFIX) $(DESTDIR)$(SHAREDLIB_DIR)/; \
cp libsrtp3.$(SHAREDLIBSUFFIXNOVER) $(DESTDIR)$(SHAREDLIB_DIR)/; \
if [ -n "$(SHAREDLIBVERSION)" ]; then \
ln -sfn libsrtp3.$(SHAREDLIBSUFFIX) $(DESTDIR)$(SHAREDLIB_DIR)/libsrtp3.$(SHAREDLIBSUFFIXNOVER); \
fi; \
fi
$(INSTALL) -d $(DESTDIR)$(pkgconfigdir)
cp $(top_builddir)/$(pkgconfig_DATA) $(DESTDIR)$(pkgconfigdir)/
uninstall:
rm -f $(DESTDIR)$(includedir)/srtp3/*.h
rm -f $(DESTDIR)$(libdir)/libsrtp3.*
-rmdir $(DESTDIR)$(includedir)/srtp3
rm -f $(DESTDIR)$(pkgconfigdir)/$(pkgconfig_DATA)
clean:
rm -rf $(cryptobj) $(srtpobj) TAGS \
libsrtp3.a libsrtp3.so libsrtp3.dll.a core *.core test/core
for a in * */* */*/*; do \
if [ -f "$$a~" ] ; then rm -f $$a~; fi; \
done;
for a in $(testapp); do rm -rf $$a$(EXE); done
rm -rf *.pict *.jpg *.dat
rm -rf freed allocated tmp
$(MAKE) -C doc clean
$(MAKE) -C fuzzer clean
superclean: clean
rm -rf crypto/include/config.h config.log config.cache config.status \
Makefile crypto/Makefile doc/Makefile \
.gdb_history test/.gdb_history .DS_Store
rm -rf autom4te.cache
distclean: superclean
distversion = $(shell cat VERSION)
distname = libsrtp-$(distversion)
mesonprojver = $(shell sed -n -e "s/project.*version\s*:\s'\([0-9.]\+\)'.*/\1/p" meson.build)
distribution: runtest superclean
if ! [ -f VERSION ]; then exit 1; fi
@# Check that the project version set in meson matches the release version
@if [ $(distversion) != $(mesonprojver) ]; then \
echo "==================================================="; \
echo "Meson project version is $(mesonprojver) which is incorrect."; \
echo "Please edit meson.build and change the 'version:'"; \
echo "field in the project() call to $(distversion)"; \
echo "==================================================="; \
exit 1; \
fi
if [ -f ../$(distname).tgz ]; then \
mv ../$(distname).tgz ../$(distname).tgz.bak; \
fi
cd ..; tar cvzf $(distname).tgz libsrtp
# EOF

556
src/libs/libsrtp/README.md Normal file
View File

@@ -0,0 +1,556 @@
[![CMake Build](https://github.com/cisco/libsrtp/actions/workflows/cmake.yml/badge.svg)](https://github.com/cisco/libsrtp/actions/workflows/cmake.yml)
[![Autotools Build](https://github.com/cisco/libsrtp/actions/workflows/autotools.yml/badge.svg)](https://github.com/cisco/libsrtp/actions/workflows/autotools.yml)
[![Autotools Build](https://github.com/cisco/libsrtp/actions/workflows/meson.yml/badge.svg)](https://github.com/cisco/libsrtp/actions/workflows/meson.yml)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/14274/badge.svg)](https://scan.coverity.com/projects/cisco-libsrtp)
[![OSS-Fuzz Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/systemd.svg)](https://oss-fuzz-build-logs.storage.googleapis.com/index.html#libsrtp)
<a name="introduction-to-libsrtp"></a>
# Introduction to libSRTP
This package provides an implementation of the Secure Real-time
Transport Protocol (SRTP), the Universal Security Transform (UST), and
a supporting cryptographic kernel. The SRTP API is documented in include/srtp.h,
and the library is in libsrtp2.a (after compilation).
This document describes libSRTP, the Open Source Secure RTP library
from Cisco Systems, Inc. RTP is the Real-time Transport Protocol, an
IETF standard for the transport of real-time data such as telephony,
audio, and video, defined by [RFC 3550](https://tools.ietf.org/html/rfc3550).
Secure RTP (SRTP) is an RTP profile for providing confidentiality to RTP data
and authentication to the RTP header and payload. SRTP is an IETF Standard,
defined in [RFC 3711](https://tools.ietf.org/html/rfc3711), and was developed
in the IETF Audio/Video Transport (AVT) Working Group. This library supports
all of the mandatory features of SRTP, but not all of the optional features. See
the [Supported Features](#supported-features) section for more detailed information.
This document is also used to generate the documentation files in the /doc/
folder where a more detailed reference to the libSRTP API and related functions
can be created (requires installing doxygen.). The reference material is created
automatically from comments embedded in some of the C header files. The
documentation is organized into modules in order to improve its clarity. These
modules do not directly correspond to files. An underlying cryptographic kernel
provides much of the basic functionality of libSRTP but is mostly undocumented
because it does its work behind the scenes.
--------------------------------------------------------------------------------
<a name="contact-us"></a>
# Contact Us
- [libsrtp@lists.packetizer.com](mailto:libsrtp@lists.packetizer.com) general mailing list for news / announcements / discussions. This is an open list, see
[https://lists.packetizer.com/mailman/listinfo/libsrtp](https://lists.packetizer.com/mailman/listinfo/libsrtp) for singing up.
- [libsrtp-security@lists.packetizer.com](mailto:libsrtp-security@lists.packetizer.com) for disclosing security issues to the libsrtp maintenance team. This is a closed list but anyone can send to it.
--------------------------------------------------------------------------------
<a name="contents"></a>
## Contents
- [Introduction to libSRTP](#introduction-to-libsrtp)
- [Contact Us](#contact-us)
- [Contents](#contents)
- [License and Disclaimer](#license-and-disclaimer)
- [libSRTP Overview](#libsrtp-overview)
- [Secure RTP Background](#secure-rtp-background)
- [Supported Features](#supported-features)
- [Implementation Notes](#implementation-notes)
- [Installing and Building libSRTP](#installing-and-building-libsrtp)
- [Changing Build Configuration](#changing-build-configuration)
- [Using Visual Studio](#using-visual-studio)
- [Applications](#applications)
- [Example Code](#example-code)
- [Credits](#credits)
- [References](#references)
--------------------------------------------------------------------------------
<a name="license-and-disclaimer"></a>
# License and Disclaimer
libSRTP is distributed under the following license, which is included
in the source code distribution. It is reproduced in the manual in
case you got the library from another source.
> Copyright (c) 2001-2017 Cisco Systems, Inc. All rights reserved.
>
> Redistribution and use in source and binary forms, with or without
> modification, are permitted provided that the following conditions
> are met:
>
> - Redistributions of source code must retain the above copyright
> notice, this list of conditions and the following disclaimer.
> - Redistributions in binary form must reproduce the above copyright
> notice, this list of conditions and the following disclaimer in
> the documentation and/or other materials provided with the distribution.
> - Neither the name of the Cisco Systems, Inc. nor the names of its
> contributors may be used to endorse or promote products derived
> from this software without specific prior written permission.
>
> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
> FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
> INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
> SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
> OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
<a name="libsrtp-overview"></a>
# libSRTP Overview
libSRTP provides functions for protecting RTP and RTCP. RTP packets
can be encrypted and authenticated (using the `srtp_protect()`
function), turning them into SRTP packets. Similarly, SRTP packets
can be decrypted and have their authentication verified (using the
`srtp_unprotect()` function), turning them into RTP packets. Similar
functions apply security to RTCP packets.
The typedef `srtp_stream_t` points to a structure holding all of the
state associated with an SRTP stream, including the keys and
parameters for cipher and message authentication functions and the
anti-replay data. A particular `srtp_stream_t` holds the information
needed to protect a particular RTP and RTCP stream. This datatype
is intentionally opaque in order to better seperate the libSRTP
API from its implementation.
Within an SRTP session, there can be multiple streams, each
originating from a particular sender. Each source uses a distinct
stream context to protect the RTP and RTCP stream that it is
originating. The typedef `srtp_t` points to a structure holding all of
the state associated with an SRTP session. There can be multiple
stream contexts associated with a single `srtp_t`. A stream context
cannot exist indepent from an `srtp_t`, though of course an `srtp_t` can
be created that contains only a single stream context. A device
participating in an SRTP session must have a stream context for each
source in that session, so that it can process the data that it
receives from each sender.
In libSRTP, a session is created using the function `srtp_create()`.
The policy to be implemented in the session is passed into this
function as an `srtp_policy_t` structure. A single one of these
structures describes the policy of a single stream. These structures
can also be linked together to form an entire session policy. A linked
list of `srtp_policy_t` structures is equivalent to a session policy.
In such a policy, we refer to a single `srtp_policy_t` as an *element*.
An `srtp_policy_t` structure contains two `srtp_crypto_policy_t` structures
that describe the cryptograhic policies for RTP and RTCP, as well as
the SRTP master key and the SSRC value. The SSRC describes what to
protect (e.g. which stream), and the `srtp_crypto_policy_t` structures
describe how to protect it. The key is contained in a policy element
because it simplifies the interface to the library. In many cases, it
is desirable to use the same cryptographic policies across all of the
streams in a session, but to use a distinct key for each stream. A
`srtp_crypto_policy_t` structure can be initialized by using either the
`srtp_crypto_policy_set_rtp_default()` or `srtp_crypto_policy_set_rtcp_default()`
functions, which set a crypto policy structure to the default policies
for RTP and RTCP protection, respectively.
--------------------------------------------------------------------------------
<a name="secure-rtp-background"></a>
## Secure RTP Background
In this section we review SRTP and introduce some terms that are used
in libSRTP. An RTP session is defined by a pair of destination
transport addresses, that is, a network address plus a pair of UDP
ports for RTP and RTCP. RTCP, the RTP control protocol, is used to
coordinate between the participants in an RTP session, e.g. to provide
feedback from receivers to senders. An *SRTP session* is
similarly defined; it is just an RTP session for which the SRTP
profile is being used. An SRTP session consists of the traffic sent
to the SRTP or SRTCP destination transport addresses. Each
participant in a session is identified by a synchronization source
(SSRC) identifier. Some participants may not send any SRTP traffic;
they are called receivers, even though they send out SRTCP traffic,
such as receiver reports.
RTP allows multiple sources to send RTP and RTCP traffic during the
same session. The synchronization source identifier (SSRC) is used to
distinguish these sources. In libSRTP, we call the SRTP and SRTCP
traffic from a particular source a *stream*. Each stream has its own
SSRC, sequence number, rollover counter, and other data. A particular
choice of options, cryptographic mechanisms, and keys is called a
*policy*. Each stream within a session can have a distinct policy
applied to it. A session policy is a collection of stream policies.
A single policy can be used for all of the streams in a given session,
though the case in which a single *key* is shared across multiple
streams requires care. When key sharing is used, the SSRC values that
identify the streams **must** be distinct. This requirement can be
enforced by using the convention that each SRTP and SRTCP key is used
for encryption by only a single sender. In other words, the key is
shared only across streams that originate from a particular device (of
course, other SRTP participants will need to use the key for
decryption). libSRTP supports this enforcement by detecting the case
in which a key is used for both inbound and outbound data.
--------------------------------------------------------------------------------
<a name="supported-features"></a>
## Supported Features
This library supports all of the mandatory-to-implement features of
SRTP (as defined in [RFC 3711](https://tools.ietf.org/html/rfc3711)). Some of these
features can be selected (or de-selected) at run time by setting an
appropriate policy; this is done using the structure `srtp_policy_t`.
Some other behaviors of the protocol can be adapted by defining an
approriate event handler for the exceptional events; see the SRTPevents
section in the generated documentation.
Some options that are described in the SRTP specification are not
supported. This includes
- key derivation rates other than zero,
- the cipher F8,
- the use of the packet index to select between master keys.
The user should be aware that it is possible to misuse this library,
and that the result may be that the security level it provides is
inadequate. If you are implementing a feature using this library, you
will want to read the Security Considerations section of [RFC 3711](https://tools.ietf.org/html/rfc3711#section-9).
In addition, it is important that you read and understand the
terms outlined in the [License and Disclaimer](#license-and-disclaimer) section.
This library also supports the AES-GCM Authenticated Encryption methods
described in [RFC 7714](https://tools.ietf.org/html/rfc7714)
--------------------------------------------------------------------------------
<a name="implementation-notes"></a>
## Implementation Notes
* It is possible to configure which 3rd party (ie openssl/nss/etc) crypto backend
libSRTP will be built with. If no 3rd party backend is set then libSRTP provides
an internal implementation of AES and Sha1. The internal implementation only
supports AES-128 & AES-256, so to use AES-192 or the AES-GCM group of ciphers a
3rd party crypto backend must be configured. For this and performance reasons it
is highly recommended to use a 3rd party crypto backend.
* The `srtp_protect()` function assumes that the buffer holding the
rtp packet has enough storage allocated that the authentication
tag can be written to the end of that packet. If this assumption
is not valid, memory corruption will ensue.
* Automated tests for the crypto functions are provided through
the `cipher_type_self_test()` and `auth_type_self_test()` functions.
These functions should be used to test each port of this code
to a new platform.
* Replay protection is contained in the crypto engine, and
tests for it are provided.
* This implementation provides calls to initialize, protect, and
unprotect RTP packets, and makes as few as possible assumptions
about how these functions will be called. For example, the
caller is not expected to provide packets in order (though if
they're called more than 65k out of sequence, synchronization
will be lost).
* The sequence number in the rtp packet is used as the low 16 bits
of the sender's local packet index. Note that RTP will start its
sequence number in a random place, and the SRTP layer just jumps
forward to that number at its first invocation. An earlier
version of this library used initial sequence numbers that are
less than 32,768; this trick is no longer required as the
`rdbx_estimate_index(...)` function has been made smarter as of
version 1.0.1.
* The replay window for (S)RTCP is hardcoded to 128 bits in length.
--------------------------------------------------------------------------------
<a name="installing-and-building-libsrtp"></a>
# Installing and Building libSRTP
To install libSRTP, download the latest release of the distribution
from [https://github.com/cisco/libsrtp/releases](https://github.com/cisco/libsrtp/releases).
You probably want to get the most recent release. Unpack the distribution and
extract the source files; the directory into which the source files
will go is named `libsrtp-A-B-C` where `A` is the version number, `B` is the
major release number and `C` is the minor release number.
libSRTP uses the GNU `autoconf` and `make` utilities (BSD make will not work; if
both versions of make are on your platform, you can invoke GNU make as
`gmake`.). In the `libsrtp` directory, run the configure script and then
make:
~~~.txt
./configure [ options ]
make
~~~
The configure script accepts the following options:
Option | Description
-------------------------------|--------------------
\-\-help \-h | Display help
\-\-enable-debug-logging | Enable debug logging in all modules
\-\-enable-openssl | Enable OpenSSL crypto engine
\-\-enable-nss | Enable NSS crypto engine
\-\-enable-openssl-kdf | Enable OpenSSL KDF algorithm
\-\-enable-log-stdout | Enable logging to stdout
\-\-with-openssl-dir | Location of OpenSSL installation
\-\-with-nss-dir | Location of NSS installation
\-\-with-log-file | Use file for logging
By default there is no log output, logging can be enabled to be output to stdout
or a given file using the configure options.
This package has been tested on the following platforms: Mac OS X
(powerpc-apple-darwin1.4), Cygwin (i686-pc-cygwin), Solaris
(sparc-sun-solaris2.6), RedHat Linux 7.1 and 9 (i686-pc-linux), and
OpenBSD (sparc-unknown-openbsd2.7).
--------------------------------------------------------------------------------
<a name="changing-build-configuration"></a>
## 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
```
--------------------------------------------------------------------------------
<a name="using-visual-studio"></a>
## Using Visual Studio
On Windows one can use Visual Studio via CMake. CMake can be downloaded here:
https://cmake.org/ . To create Visual Studio build files, for example run the
following commands:
```
# Create build subdirectory
mkdir build
cd build
# Make project files
cmake .. -G "Visual Studio 15 2017"
# Or for 64 bit project files
cmake .. -G "Visual Studio 15 2017 Win64"
```
--------------------------------------------------------------------------------
<a name="using-meson"></a>
## Using Meson
On all platforms including Windows, one can build using [Meson](https://mesonbuild.com).
Steps to download Meson are here: https://mesonbuild.com/Getting-meson.html
To build with Meson, you can do something like:
```
# Setup the build subdirectory
meson setup --prefix=/path/to/prefix builddir
# Build the project
meson compile -C builddir
# Run tests
meson test -C builddir
# Optionally, install
meson install -C builddir
```
To build with Visual Studio, run the above commands from inside a Visual Studio
command prompt, or run `vcvarsall.bat` with the appropriate arguments inside
a Command Prompt.
Note that you can also replace the above commands with the appropriate `ninja`
targets: `ninja -C build`, `ninja -C build test`, `ninja -C build install`.
--------------------------------------------------------------------------------
<a name="applications"></a>
# Applications
Several test drivers and a simple and portable srtp application are
included in the `test/` subdirectory.
Test driver | Function tested
--------- | -------
kernel_driver | crypto kernel (ciphers, auth funcs, rng)
srtp_driver | srtp in-memory tests (does not use the network)
rdbx_driver | rdbx (extended replay database)
roc_driver | extended sequence number functions
replay_driver | replay database
cipher_driver | ciphers
auth_driver | hash functions
The app `rtpw` is a simple rtp application which reads words from
`/usr/dict/words` and then sends them out one at a time using [s]rtp.
Manual srtp keying uses the -k option; automated key management
using gdoi will be added later.
usage:
~~~.txt
rtpw [[-d <debug>]* [-k|b <key> [-a][-e <key size>][-g]] [-s | -r] dest_ip dest_port] | [-l]
~~~
Either the -s (sender) or -r (receiver) option must be chosen. The
values `dest_ip`, `dest_port` are the IP address and UDP port to which
the dictionary will be sent, respectively.
The options are:
Option | Description
--------- | -------
-s | (S)RTP sender - causes app to send words
-r | (S)RTP receive - causes app to receive words
-k <key> | use SRTP master key <key>, where the key is a hexadecimal (without the leading "0x")
-b <key> | same as -k but with base64 encoded key
-e <keysize> | encrypt/decrypt (for data confidentiality) (requires use of -k option as well) (use 128, 192, or 256 for keysize)
-g | use AES-GCM mode (must be used with -e)
-a | message authentication (requires use of -k option as well)
-l | list the available debug modules
-d <debug> | turn on debugging for module <debug>
In order to get random 30-byte values for use as key/salt pairs , you
can use the following bash function to format the output of
`/dev/random` (where that device is available).
~~~.txt
function randhex() {
cat /dev/random | od --read-bytes=32 --width=32 -x | awk '{ print $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 $16 }'
}
~~~
An example of an SRTP session using two rtpw programs follows:
~~~.txt
set k=c1eec3717da76195bb878578790af71c4ee9f859e197a414a78d5abc7451
[sh1]$ test/rtpw -s -k $k -e 128 -a 0.0.0.0 9999
Security services: confidentiality message authentication
set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC7451
setting SSRC to 2078917053
sending word: A
sending word: a
sending word: aa
sending word: aal
...
[sh2]$ test/rtpw -r -k $k -e 128 -a 0.0.0.0 9999
security services: confidentiality message authentication
set master key/salt to C1EEC3717DA76195BB878578790AF71C/4EE9F859E197A414A78D5ABC7451
19 octets received from SSRC 2078917053 word: A
19 octets received from SSRC 2078917053 word: a
20 octets received from SSRC 2078917053 word: aa
21 octets received from SSRC 2078917053 word: aal
...
~~~
--------------------------------------------------------------------------------
<a name="example-code"></a>
## Example Code
This section provides a simple example of how to use libSRTP. The
example code lacks error checking, but is functional. Here we assume
that the value ssrc is already set to describe the SSRC of the stream
that we are sending, and that the functions `get_rtp_packet()` and
`send_srtp_packet()` are available to us. The former puts an RTP packet
into the buffer and returns the number of octets written to that
buffer. The latter sends the RTP packet in the buffer, given the
length as its second argument.
~~~.c
srtp_t session;
srtp_policy_t policy;
// Set key to predetermined value
uint8_t key[30] = {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};
// initialize libSRTP
srtp_init();
// default policy values
memset(&policy, 0x0, sizeof(srtp_policy_t));
// set policy to describe a policy for an SRTP stream
srtp_crypto_policy_set_rtp_default(&policy.rtp);
srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
policy.ssrc = ssrc;
policy.key = key;
policy.next = NULL;
// allocate and initialize the SRTP session
srtp_create(&session, &policy);
// main loop: get rtp packets, send srtp packets
while (1) {
char rtp_buffer[2048];
size_t rtp_len;
char srtp_buffer[2048];
size_t srtp_len = sizeof(srtp_buffer);
len = get_rtp_packet(rtp_buffer);
srtp_protect(session, rtp_buffer, rtp_len, srtp_buffer, &srtp_len);
send_srtp_packet(srtp_buffer, srtp_len);
}
~~~
--------------------------------------------------------------------------------
<a name="credits"></a>
# Credits
The original implementation and documentation of libSRTP was written
by David McGrew of Cisco Systems, Inc. in order to promote the use,
understanding, and interoperability of Secure RTP. Michael Jerris
contributed support for building under MSVC. Andris Pavenis
contributed many important fixes. Brian West contributed changes to
enable dynamic linking. Yves Shumann reported documentation bugs.
Randell Jesup contributed a working SRTCP implementation and other
fixes. Steve Underwood contributed x86_64 portability changes. We also give
thanks to Fredrik Thulin, Brian Weis, Mark Baugher, Jeff Chan, Bill
Simon, Douglas Smith, Bill May, Richard Preistley, Joe Tardo and
others for contributions, comments, and corrections.
This reference material, when applicable, in this documenation was generated
using the doxygen utility for automatic documentation of source code.
Copyright 2001-2005 by David A. McGrew, Cisco Systems, Inc.
--------------------------------------------------------------------------------
<a name="references"></a>
# References
SRTP and ICM References
September, 2005
Secure RTP is defined in [RFC 3711](https://tools.ietf.org/html/rfc3711).
The counter mode definition is in [Section 4.1.1](https://tools.ietf.org/html/rfc3711#section-4.1.1).
SHA-1 is defined in [FIPS PUB 180-4](http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).
HMAC is defined in [RFC 2104](https://tools.ietf.org/html/rfc2104)
and HMAC-SHA1 test vectors are available
in [RFC 2202](https://tools.ietf.org/html/rfc2202#section-3).
AES-GCM usage in SRTP is defined in [RFC 7714](https://tools.ietf.org/html/rfc7714)

1456
src/libs/libsrtp/config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

202
src/libs/libsrtp/config.h Normal file
View File

@@ -0,0 +1,202 @@
/* config_in.h. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define if building for a CISC machine (e.g. Intel). */
#undef CPU_CISC
/* 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 this to use AES-GCM. */
#undef GCM
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define to 1 if you have the <byteswap.h> header file. */
#undef HAVE_BYTESWAP_H
/* Define to 1 if you have the `inet_aton' function. */
#undef HAVE_INET_ATON
/* Define to 1 if you have the `inet_pton' function. */
#undef HAVE_INET_PTON
/* Define to 1 if the system has the type `int16_t'. */
#undef HAVE_INT16_T
/* Define to 1 if the system has the type `int32_t'. */
#undef HAVE_INT32_T
/* Define to 1 if the system has the type `int8_t'. */
#undef HAVE_INT8_T
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `dl' library (-ldl). */
#undef HAVE_LIBDL
/* Define to 1 if you have the `nspr4' library (-lnspr4). */
#undef HAVE_LIBNSPR4
/* Define to 1 if you have the `nss3' library (-lnss3). */
#undef HAVE_LIBNSS3
/* Define to 1 if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
/* Define to 1 if you have the <machine/types.h> header file. */
#undef HAVE_MACHINE_TYPES_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the <nss.h> header file. */
#undef HAVE_NSS_H
/* Define to 1 if you have the `winpcap' library (-lwpcap) */
#undef HAVE_PCAP
/* Define to 1 if you have the `sigaction' function. */
#undef HAVE_SIGACTION
/* Define to 1 if you have the `socket' function. */
#undef HAVE_SOCKET
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/int_types.h> header file. */
#undef HAVE_SYS_INT_TYPES_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/uio.h> header file. */
#undef HAVE_SYS_UIO_H
/* Define to 1 if the system has the type `uint16_t'. */
#undef HAVE_UINT16_T
/* Define to 1 if the system has the type `uint32_t'. */
#undef HAVE_UINT32_T
/* Define to 1 if the system has the type `uint64_t'. */
#undef HAVE_UINT64_T
/* Define to 1 if the system has the type `uint8_t'. */
#undef HAVE_UINT8_T
/* Define to 1 if you have the <unistd.h> 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 <windows.h> header file. */
#undef HAVE_WINDOWS_H
/* Define to 1 if you have the <winsock2.h> header file. */
#undef HAVE_WINSOCK2_H
/* Define to use X86 inlined assembly code */
#undef HAVE_X86
/* Define this to use NSS crypto. */
#undef NSS
/* Define this to use OpenSSL crypto. */
#undef OPENSSL
/* Define this to use OpenSSL KDF for SRTP. */
#undef OPENSSL_KDF
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* The size of `unsigned long', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_LONG
/* The size of `unsigned long long', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_LONG_LONG
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define this to use wolfSSL crypto. */
#undef WOLFSSL
/* Define this to use wolfSSL KDF for SRTP. */
#undef WOLFSSL_KDF
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

1815
src/libs/libsrtp/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,202 @@
/* config_in.h. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define if building for a CISC machine (e.g. Intel). */
#undef CPU_CISC
/* 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 this to use AES-GCM. */
#undef GCM
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define to 1 if you have the <byteswap.h> header file. */
#undef HAVE_BYTESWAP_H
/* Define to 1 if you have the `inet_aton' function. */
#undef HAVE_INET_ATON
/* Define to 1 if you have the `inet_pton' function. */
#undef HAVE_INET_PTON
/* Define to 1 if the system has the type `int16_t'. */
#undef HAVE_INT16_T
/* Define to 1 if the system has the type `int32_t'. */
#undef HAVE_INT32_T
/* Define to 1 if the system has the type `int8_t'. */
#undef HAVE_INT8_T
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `dl' library (-ldl). */
#undef HAVE_LIBDL
/* Define to 1 if you have the `nspr4' library (-lnspr4). */
#undef HAVE_LIBNSPR4
/* Define to 1 if you have the `nss3' library (-lnss3). */
#undef HAVE_LIBNSS3
/* Define to 1 if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
/* Define to 1 if you have the <machine/types.h> header file. */
#undef HAVE_MACHINE_TYPES_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the <nss.h> header file. */
#undef HAVE_NSS_H
/* Define to 1 if you have the `winpcap' library (-lwpcap) */
#undef HAVE_PCAP
/* Define to 1 if you have the `sigaction' function. */
#undef HAVE_SIGACTION
/* Define to 1 if you have the `socket' function. */
#undef HAVE_SOCKET
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/int_types.h> header file. */
#undef HAVE_SYS_INT_TYPES_H
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/uio.h> header file. */
#undef HAVE_SYS_UIO_H
/* Define to 1 if the system has the type `uint16_t'. */
#undef HAVE_UINT16_T
/* Define to 1 if the system has the type `uint32_t'. */
#undef HAVE_UINT32_T
/* Define to 1 if the system has the type `uint64_t'. */
#undef HAVE_UINT64_T
/* Define to 1 if the system has the type `uint8_t'. */
#undef HAVE_UINT8_T
/* Define to 1 if you have the <unistd.h> 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 <windows.h> header file. */
#undef HAVE_WINDOWS_H
/* Define to 1 if you have the <winsock2.h> header file. */
#undef HAVE_WINSOCK2_H
/* Define to use X86 inlined assembly code */
#undef HAVE_X86
/* Define this to use NSS crypto. */
#undef NSS
/* Define this to use OpenSSL crypto. */
#undef OPENSSL
/* Define this to use OpenSSL KDF for SRTP. */
#undef OPENSSL_KDF
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* The size of `unsigned long', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_LONG
/* The size of `unsigned long long', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_LONG_LONG
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define this to use wolfSSL crypto. */
#undef WOLFSSL
/* Define this to use wolfSSL KDF for SRTP. */
#undef WOLFSSL_KDF
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t

View File

@@ -0,0 +1,141 @@
/* clang-format off */
/* Define to the full name and version of this package. */
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
/* Define to the version of this package. */
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
/* Define to enabled debug logging for all mudules. */
#cmakedefine ENABLE_DEBUG_LOGGING 1
/* Logging statments will be writen to this file. */
#cmakedefine ERR_REPORTING_FILE "@ERR_REPORTING_FILE@"
/* Define to redirect logging to stdout. */
#cmakedefine ERR_REPORTING_STDOUT 1
/* Define this to use OpenSSL crypto. */
#cmakedefine OPENSSL 1
/* Define this to use wolfSSL crypto. */
#cmakedefine WOLFSSL 1
/* Define this to use wolfSSL SRTP-KDF. */
#cmakedefine WOLFSSL_KDF 1
/* Define this to use MBEDTLS. */
#cmakedefine MBEDTLS 1
/* Define this to use NSS crypto. */
#cmakedefine NSS 1
/* Define this to use AES-GCM. */
#cmakedefine GCM 1
/* 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 use X86 inlined assembly code */
#cmakedefine HAVE_X86 1
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#cmakedefine WORDS_BIGENDIAN 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
#cmakedefine HAVE_ARPA_INET_H 1
/* Define to 1 if you have the <byteswap.h> header file. */
#cmakedefine HAVE_BYTESWAP_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
/* Define to 1 if you have the <machine/types.h> header file. */
#cmakedefine HAVE_MACHINE_TYPES_H 1
/* Define to 1 if you have the <netinet/in.h> header file. */
#cmakedefine HAVE_NETINET_IN_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H 1
/* Define to 1 if you have the <sys/int_types.h> header file. */
#cmakedefine HAVE_SYS_INT_TYPES_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#cmakedefine HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
/* Define to 1 if you have the <windows.h> header file. */
#cmakedefine HAVE_WINDOWS_H 1
/* Define to 1 if you have the <winsock2.h> header file. */
#cmakedefine HAVE_WINSOCK2_H 1
/* Define to 1 if you have the `inet_aton' function. */
#cmakedefine HAVE_INET_ATON 1
/* Define to 1 if you have the `inet_pton' function. */
#cmakedefine HAVE_INET_PTON 1
/* Define to 1 if you have the `sigaction' function. */
#cmakedefine HAVE_SIGACTION 1
/* Define to 1 if you have the `usleep' function. */
#cmakedefine HAVE_USLEEP 1
/* Define to 1 if the system has the type `uint8_t'. */
#cmakedefine HAVE_UINT8_T 1
/* Define to 1 if the system has the type `uint16_t'. */
#cmakedefine HAVE_UINT16_T 1
/* Define to 1 if the system has the type `uint32_t'. */
#cmakedefine HAVE_UINT32_T 1
/* Define to 1 if the system has the type `uint64_t'. */
#cmakedefine HAVE_UINT64_T 1
/* Define to 1 if the system has the type `int32_t'. */
#cmakedefine HAVE_INT32_T 1
/* The size of `unsigned long', as computed by sizeof. */
@SIZEOF_UNSIGNED_LONG_CODE@
/* The size of `unsigned long long', as computed by sizeof. */
@SIZEOF_UNSIGNED_LONG_LONG_CODE@
/* Define inline to what is supported by compiler */
#cmakedefine HAVE_INLINE 1
#cmakedefine HAVE___INLINE 1
#ifndef HAVE_INLINE
#ifdef HAVE___INLINE
#define inline __inline
#else
#define inline
#endif
#endif
/* Define gcc/clang-style SSE macros on compilers that don't define them (primarilly, MSVC). */
#if !defined(__SSE2__) && (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2))
#define __SSE2__
#endif
#if !defined(__SSSE3__) && defined(__AVX__)
#define __SSSE3__
#endif
#if !defined(__SSE4_1__) && defined(__AVX__)
#define __SSE4_1__
#endif

7846
src/libs/libsrtp/configure vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,434 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT([libsrtp3],[3.0.0-pre],[https://github.com/cisco/libsrtp/issues])
dnl Must come before AC_PROG_CC
EMPTY_CFLAGS="no"
if test "x$CFLAGS" = "x"; then
dnl Default value for CFLAGS if not specified.
EMPTY_CFLAGS="yes"
fi
dnl Checks for programs.
AC_PROG_CC
AC_PROG_CPP
AC_PROG_CXX
AC_ARG_VAR(
[EXTRA_CFLAGS],
[C compiler flags appended to the regular C compiler flags instead of overriding them])
AM_PROG_AR
AC_PROG_RANLIB
AC_PROG_INSTALL
AC_PROG_SED
dnl Check the byte order
AC_C_BIGENDIAN
AC_CANONICAL_HOST
dnl check host_cpu type, set defines appropriately
case $host_cpu in
i*86 | x86_64 )
AC_DEFINE([CPU_CISC], [1], [Define if building for a CISC machine (e.g. Intel).])
AC_DEFINE([HAVE_X86], [1], [Define to use X86 inlined assembly code])
;;
* )
AC_DEFINE([CPU_RISC], [1], [Define if building for a RISC machine (assume slow byte access).])
;;
esac
dnl Check if we are on a Windows platform.
case $host_os in
*cygwin*|*mingw* )
EXE=.exe
;;
* )
EXE=""
;;
esac
AC_SUBST([EXE]) # define executable suffix; this is needed for `make clean'
dnl Checks for supported compiler flags.
supported_cflags=""
if test "$EMPTY_CFLAGS" = "no"; then
supported_cflags="$CFLAGS"
fi
dnl For accurate detection, we need warnings as errors.
dnl I.e. Clang will issue a warning about unsupported flags.
dnl For the compilation to fail, those warnings needs to be upgraded to errors.
dnl This will be removed again once the tests are complete (see below).
WERROR=""
for w in -Werror -errwarn; do
if test "x$WERROR" = "x"; then
AC_MSG_CHECKING([whether ${CC-c} accepts $w])
save_cflags="$CFLAGS"
AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$w"], [CFLAGS="$CFLAGS $w"])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])],
[WERROR="$w"
AC_MSG_RESULT([yes])],
[CFLAGS="$save_cflags"
AC_MSG_RESULT([no])])
fi
done
dnl Note that -fPIC is not explicitly added to LDFLAGS.
dnl Since the compiler is used as the link driver, CFLAGS will be part of the
dnl link line as well and the linker will get the flag from there.
dnl Adding it to LDFLAGS explicitly would duplicate the flag on the link line,
dnl but otherwise do no harm.
AC_MSG_CHECKING([whether ${CC-c} accepts -fPIC])
save_cflags="$CFLAGS"
AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="-fPIC"], [CFLAGS="$CFLAGS -fPIC"])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])],
[AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="-fPIC"], [supported_cflags="$supported_cflags -fPIC"])
AC_MSG_RESULT([yes])],
[CFLAGS="$save_cflags"
AC_MSG_RESULT([no])])
if test "$EMPTY_CFLAGS" = "yes"; then
for f in -Wall -pedantic -Wstrict-prototypes; do
AC_MSG_CHECKING([whether ${CC-c} accepts $f])
save_cflags="$CFLAGS"
AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$f"], [CFLAGS="$CFLAGS $f"])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])],
[AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="$f"], [supported_cflags="$supported_cflags $f"])
AC_MSG_RESULT([yes])],
[CFLAGS="$save_cflags"
AC_MSG_RESULT([no])])
done
OOPT=""
for f in -O3; do
if test "x$OOPT" = "x"; then
AC_MSG_CHECKING([whether ${CC-c} accepts $f])
save_cflags="$CFLAGS"
AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$f"], [CFLAGS="$CFLAGS $f"])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])],
[AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="$f"], [supported_cflags="$supported_cflags $f"])
OOPT="$f"
AC_MSG_RESULT([yes])],
[CFLAGS="$save_cflags"
AC_MSG_RESULT([no])])
fi
done
for f in -fexpensive-optimizations -funroll-loops; do
AC_MSG_CHECKING([whether ${CC-c} accepts $f])
save_cflags="$CFLAGS"
AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$f"], [CFLAGS="$CFLAGS $f"])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])],
[AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="$f"], [supported_cflags="$supported_cflags $f"])
AC_MSG_RESULT([yes])],
[CFLAGS="$save_cflags"
AC_MSG_RESULT([no])])
done
fi
dnl When turning off warnigns, we're expecting unrecognized command line option errors if they're not
dnl supported. However, the -Wno-<warning> form isn't consulted unless a warning is triggered.
dnl At least that's the case for GCC. So to check which warnings we can turn off, we need to check
dnl if they can be turned on, thereby forcing GCC to take the argument into account right away.
for f in -Wno-language-extension-token; do
AC_MSG_CHECKING([whether ${CC-c} accepts $f])
save_cflags="$CFLAGS"
testf=$(echo "$f" | $SED 's|-Wno-\(.*\)|-W\1|g')
AS_IF([test "x$CFLAGS" = "x"], [CFLAGS="$testf"], [CFLAGS="$CFLAGS $testf"])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) { return 0; }])],
[AS_IF([test "x$supported_cflags" = "x"], [supported_cflags="$f"], [supported_cflags="$supported_cflags $f"])
AC_MSG_RESULT([yes])],
[CFLAGS="$save_cflags"
AC_MSG_RESULT([no])])
done
dnl Remowing -Werror again
CFLAGS="$supported_cflags"
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(
[unistd.h byteswap.h stdint.h sys/uio.h inttypes.h sys/types.h machine/types.h sys/int_types.h],
[], [], [AC_INCLUDES_DEFAULT])
dnl socket() and friends
AC_CHECK_HEADERS([sys/socket.h netinet/in.h arpa/inet.h], [], [], [AC_INCLUDES_DEFAULT])
AC_CHECK_HEADERS(
[windows.h],
[AC_CHECK_HEADERS([winsock2.h], [], [], [AC_INCLUDES_DEFAULT])],
[], [AC_INCLUDES_DEFAULT])
AC_CHECK_TYPES([int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, uint64_t])
AC_CHECK_SIZEOF([unsigned long])
AC_CHECK_SIZEOF([unsigned long long])
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
AC_TYPE_SIZE_T
dnl Checks for library functions.
AC_CHECK_FUNCS([socket inet_aton inet_pton usleep sigaction])
dnl Find socket function if not found yet.
if test "x$ac_cv_func_socket" = "xno"; then
AC_CHECK_LIB([socket], [socket])
AC_MSG_CHECKING([for socket in -lwsock32])
SAVELIBS="$LIBS"
LIBS="$LIBS -lwsock32"
AC_LINK_IFELSE(
[AC_LANG_SOURCE([
#include <winsock2.h>
int main(void)
{
int fd = socket(0, 0, 0);
if (fd < 0)
return -1;
else
return 0;
}
])],
[ac_cv_func_socket=yes
AC_MSG_RESULT([yes])],
[LIBS="$SAVELIBS"
AC_MSG_RESULT([no])])
fi
AC_MSG_CHECKING([whether to enable debug logging in all modules])
AC_ARG_ENABLE([debug-logging],
[AS_HELP_STRING([--enable-debug-logging], [Enable debug logging in all modules])],
[], enable_debug_logging=no)
if test "$enable_debug_logging" = "yes"; then
AC_DEFINE([ENABLE_DEBUG_LOGGING], [1], [Define to enabled debug logging for all mudules.])
fi
AC_MSG_RESULT([$enable_debug_logging])
PKG_PROG_PKG_CONFIG
AS_IF([test "x$PKG_CONFIG" != "x"], [PKG_CONFIG="$PKG_CONFIG --static"])
AC_MSG_CHECKING([for crypto library])
AC_ARG_WITH([crypto-library], AS_HELP_STRING([--with-crypto-library=TYPE], [Select crypto library, one of: internal, openssl, wolfssl, nss]),
[case "$with_crypto_library" in
internal) ;;
openssl) enable_openssl=yes ;;
wolfssl) enable_wolfssl=yes ;;
nss) enable_nss=yes ;;
*) AC_MSG_ERROR([Invalid crypto library: $with_crypto_library. Select one of: internal, openssl, wolfssl, nss,]) ;;
esac],
[with_crypto_library=internal])
AC_MSG_RESULT([$with_crypto_library])
if test "$enable_openssl" = "yes"; then
AC_MSG_CHECKING([for user specified OpenSSL directory])
AC_ARG_WITH([openssl-dir],
[AS_HELP_STRING([--with-openssl-dir], [Location of OpenSSL installation])],
[if test "x$PKG_CONFIG" != "x" && test -f $with_openssl_dir/lib/pkgconfig/libcrypto.pc; then
if test "x$PKG_CONFIG_PATH" = "x"; then
export PKG_CONFIG_PATH="$with_openssl_dir/lib/pkgconfig"
else
export PKG_CONFIG_PATH="$with_openssl_dir/lib/pkgconfig:$PKG_CONFIG_PATH"
fi
AC_MSG_RESULT([$with_openssl_dir])
elif test -d $with_openssl_dir/lib; then
CFLAGS="$CFLAGS -I$with_openssl_dir/include"
if test "x$LDFLAGS" = "x"; then
LDFLAGS="-L$with_openssl_dir/lib"
else
LDFLAGS="$LDFLAGS -L$with_openssl_dir/lib"
fi
AC_MSG_RESULT([$with_openssl_dir])
else
AC_MSG_RESULT([invalid])
AC_MSG_FAILURE([Invalid OpenSSL location: $with_openssl_dir])
fi],
[AC_MSG_RESULT([no])])
if test "x$PKG_CONFIG" != "x"; then
PKG_CHECK_MODULES([crypto], [libcrypto],
[CFLAGS="$CFLAGS $crypto_CFLAGS"
LIBS="$crypto_LIBS $LIBS"])
else
AC_CHECK_LIB([dl], [dlopen], [], [AC_MSG_WARN([can't find libdl])])
AC_CHECK_LIB([z], [inflate], [], [AC_MSG_WARN([can't find libz])])
fi
AC_SEARCH_LIBS([EVP_EncryptInit], [crypto],
[], [AC_MSG_FAILURE([can't find compatible openssl crypto lib])])
AC_SEARCH_LIBS([EVP_aes_128_ctr], [crypto],
[], [AC_MSG_FAILURE([can't find compatible openssl crypto lib])])
AC_SEARCH_LIBS([EVP_aes_128_gcm], [crypto],
[], [AC_MSG_FAILURE([can't find compatible openssl crypto lib])])
AC_SEARCH_LIBS([EVP_CIPHER_CTX_reset], [crypto],
[], [AC_MSG_FAILURE([can't find compatible openssl crypto lib])])
AC_DEFINE([GCM], [1], [Define this to use AES-GCM.])
AC_DEFINE([OPENSSL], [1], [Define this to use OpenSSL crypto.])
AES_ICM_OBJS="crypto/cipher/aes_icm_ossl.o crypto/cipher/aes_gcm_ossl.o"
HMAC_OBJS=crypto/hash/hmac_ossl.o
AC_SUBST([USE_EXTERNAL_CRYPTO], [1])
AC_MSG_CHECKING([whether to leverage OpenSSL KDF algorithm])
AC_ARG_ENABLE([openssl-kdf],
[AS_HELP_STRING([--enable-openssl-kdf], [Use OpenSSL KDF algorithm])],
[], [enable_openssl_kdf=no])
AC_MSG_RESULT([$enable_openssl_kdf])
if test "$enable_openssl_kdf" = "yes"; then
AC_SEARCH_LIBS([kdf_srtp], [crypto],
[], [AC_MSG_FAILURE([can't find openssl KDF lib])])
AC_DEFINE([OPENSSL_KDF], [1], [Define this to use OpenSSL KDF for SRTP.])
fi
elif test "$enable_wolfssl" = "yes"; then
AC_MSG_CHECKING([for user specified wolfSSL directory])
AC_ARG_WITH([wolfssl-dir],
[AS_HELP_STRING([--with-wolfssl-dir], [Location of wolfSSL installation])],
[if test -d $with_wolfssl_dir/lib; then
CFLAGS="$CFLAGS -I$with_wolfssl_dir/include -I$with_wolfssl_dir/include/wolfssl"
if test "x$LDFLAGS" = "x"; then
LDFLAGS="-L$with_wolfssl_dir/lib"
else
LDFLAGS="$LDFLAGS -L$with_wolfssl_dir/lib"
fi
AC_MSG_RESULT([$with_wolfssl_dir])
else
AC_MSG_RESULT([invalid])
AC_MSG_FAILURE([Invalid wolfSSL location: $with_wolfssl_dir])
fi],
[AC_MSG_RESULT([no])])
AC_CHECK_LIB([dl], [dlopen], [], [AC_MSG_WARN([can't find libdl])])
AC_DEFINE([GCM], [1], [Define this to use AES-GCM.])
AC_DEFINE([WOLFSSL], [1], [Define this to use wolfSSL crypto.])
AES_ICM_OBJS="crypto/cipher/aes_icm_wssl.o crypto/cipher/aes_gcm_wssl.o"
HMAC_OBJS=crypto/hash/hmac_wssl.o
AC_SUBST([USE_EXTERNAL_CRYPTO], [1])
AC_MSG_CHECKING([whether to leverage wolfSSL KDF algorithm])
AC_SEARCH_LIBS([wc_SRTCP_KDF], [wolfssl],
[], [AC_MSG_FAILURE([can't find wolfssl KDF lib])])
AC_DEFINE([WOLFSSL_KDF], [1], [Define this to use wolfSSL KDF for SRTP.])
elif test "$enable_nss" = "yes"; then
AC_MSG_CHECKING([for user specified NSS directory])
AC_ARG_WITH([nss-dir],
[AS_HELP_STRING([--with-nss-dir], [Location of NSS installation])],
[if test "x$PKG_CONFIG" != "x" && test -f $with_nss_dir/lib/pkgconfig/nss.pc; then
if test "x$PKG_CONFIG_PATH" = "x"; then
export PKG_CONFIG_PATH="$with_nss_dir/lib/pkgconfig"
else
export PKG_CONFIG_PATH="$with_nss_dir/lib/pkgconfig:$PKG_CONFIG_PATH"
fi
AC_MSG_RESULT([$with_nss_dir])
elif test -d $with_nss_dir/lib; then
CFLAGS="$CFLAGS -I$with_nss_dir/include"
CFLAGS="$CFLAGS -I$with_nss_dir/../public/nss"
if test "x$LDFLAGS" = "x"; then
LDFLAGS="-L$with_nss_dir/lib"
else
LDFLAGS="$LDFLAGS -L$with_nss_dir/lib"
fi
nss_skip_pkg_config=yes
AC_MSG_RESULT([$with_nss_dir])
else
AC_MSG_RESULT([invalid])
AC_MSG_FAILURE([Invalid NSS location: $with_nss_dir])
fi
AC_SUBST([CRYPTO_LIBDIR], [$with_nss_dir/lib])],
[AC_MSG_RESULT([no])])
if test "x$PKG_CONFIG" != "x" && test "$nss_skip_pkg_config" != "yes"; then
PKG_CHECK_MODULES([nss], [nss],
[CFLAGS="$CFLAGS $nss_CFLAGS"
LIBS="$nss_LIBS $LIBS"])
else
AC_CHECK_HEADERS(
[nss.h],
[], [AC_MSG_FAILURE([can't find useable NSS headers])],
[AC_INCLUDES_DEFAULT])
AC_CHECK_LIB(
[nspr4], [PR_GetError],
[], [AC_MSG_WARN([can't find libnspr4])])
AC_CHECK_LIB(
[nss3], [NSS_NoDB_Init],
[], [AC_MSG_FAILURE([can't find useable libnss3])])
fi
AC_DEFINE([GCM], [1], [Define this to use AES-GCM.])
AC_DEFINE([NSS], [1], [Define this to use NSS crypto.])
AES_ICM_OBJS="crypto/cipher/aes_icm_nss.o crypto/cipher/aes_gcm_nss.o"
HMAC_OBJS="crypto/hash/hmac_nss.o"
# TODO(RLB): Use NSS for KDF
AC_SUBST([USE_EXTERNAL_CRYPTO], [1])
else
AES_ICM_OBJS="crypto/cipher/aes_icm.o crypto/cipher/aes.o"
HMAC_OBJS="crypto/hash/hmac.o crypto/hash/sha1.o"
fi
AC_SUBST([AES_ICM_OBJS])
AC_SUBST([HMAC_OBJS])
dnl Checking for PCAP
PCAP_LIB=""
AC_ARG_ENABLE([pcap], AS_HELP_STRING([--disable-pcap], [Build without `pcap' library (-lpcap)]))
AS_IF([test "x$enable_pcap" != "xno"], [
AC_CHECK_LIB([pcap], [pcap_create],
[PCAP_LIB="-lpcap"
AC_DEFINE([HAVE_PCAP], [1], [Define to 1 if you have the `pcap' library (-lpcap)])
AC_SUBST([HAVE_PCAP], [1])])
AC_CHECK_LIB([wpcap], [pcap_create],
[PCAP_LIB="-lwpcap"
AC_DEFINE([HAVE_PCAP], [1], [Define to 1 if you have the `winpcap' library (-lwpcap)])
AC_SUBST([HAVE_PCAP], [1])])
])
AC_SUBST([PCAP_LIB])
AC_MSG_CHECKING([whether to redirect logging to stdout])
AC_ARG_ENABLE([log-stdout],
[AS_HELP_STRING([--enable-log-stdout], [redirecting logging to stdout])],
[], [enable_log_stdout=no])
if test "$enable_log_stdout" = "yes"; then
AC_DEFINE([ERR_REPORTING_STDOUT], [1], [Define to redirect logging to stdout.])
fi
AC_MSG_RESULT([$enable_log_stdout])
AC_MSG_CHECKING([wheather to use a file for logging])
AC_ARG_WITH([log-file],
[AS_HELP_STRING([--with-log-file], [Use file for logging])],
[AS_CASE([x$with_log_file],
[x], [valid_with_log_file="no"],
[xyes], [valid_with_log_file="no"],
[valid_with_error_file="yes"])
AS_IF([test "$valid_with_log_file" = "no"],
[AC_MSG_RESULT([invalid])
AC_MSG_FAILURE([Invalid value for --with-log-file: "$with_log_file"])],
[AC_DEFINE_UNQUOTED([ERR_REPORTING_FILE], ["$with_log_file"], [Logging statments will be writen to this file.])
AC_MSG_RESULT([using log file: "$with_log_file"])])],
[AC_MSG_RESULT([no])])
AS_IF(
[test "$enable_log_stdout" = "yes" && test "x$with_log_file" != "x"],
[AC_MSG_FAILURE([Can only use one of --enable-log-stdout and --with-log-file; they are mutually exclusive])])
dnl Appending EXTRA_CFLAGS, if given
AC_MSG_CHECKING([for extra C compiler flags])
AS_IF([test "x$EXTRA_CFLAGS" != "x"],
[AS_IF([test "x$CFLAGS" = "x"],
[CFLAGS="$EXTRA_CFLAGS"], [CFLAGS="$CFLAGS $EXTRA_CFLAGS"])
AC_MSG_RESULT([$EXTRA_CFLAGS])],
[AC_MSG_RESULT(no)])
AC_CONFIG_HEADER([crypto/include/config.h:config_in.h])
AC_CONFIG_FILES([Makefile crypto/Makefile doc/Makefile fuzzer/Makefile libsrtp3.pc])
AC_OUTPUT
# This is needed when building outside the source dir.
AS_MKDIR_P([crypto/cipher])
AS_MKDIR_P([crypto/hash])
AS_MKDIR_P([crypto/kernel])
AS_MKDIR_P([crypto/math])
AS_MKDIR_P([crypto/replay])
AS_MKDIR_P([crypto/test])
AS_MKDIR_P([doc])
AS_MKDIR_P([srtp])
AS_MKDIR_P([test])

View File

@@ -0,0 +1,118 @@
# Makefile for crypto test suite
#
# David A. McGrew
# Cisco Systems, Inc.
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
VPATH = @srcdir@
CC = @CC@
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 = -lsrtp3
CRYPTO_LIBDIR = @CRYPTO_LIBDIR@
RANLIB = @RANLIB@
# Specify how tests should find shared libraries on macOS and Linux
#
# macOS purges DYLD_LIBRARY_PATH when spawning subprocesses, so it's
# not possible to pass this in from the outside; we have to specify
# it for any subprocesses we call. No support for dynamic linked
# tests on Windows.
ifneq ($(strip $(CRYPTO_LIBDIR)),)
ifneq ($(OS),Windows_NT)
UNAME_S = $(shell uname -s)
ifeq ($(UNAME_S),Linux)
FIND_LIBRARIES = LD_LIBRARY_PATH=$(CRYPTO_LIBDIR)
endif
ifeq ($(UNAME_S),Darwin)
FIND_LIBRARIES = DYLD_LIBRARY_PATH=$(CRYPTO_LIBDIR)
endif
endif
endif
# EXE defines the suffix on executables - it's .exe for cygwin, and
# null on linux, bsd, and OS X and other OSes. we define this so that
# `make clean` will work on the cygwin platform
EXE = @EXE@
# Random source.
USE_EXTERNAL_CRYPTO = @USE_EXTERNAL_CRYPTO@
ifdef ARCH
DEFS += -D$(ARCH)=1
endif
ifdef sysname
DEFS += -D$(sysname)=1
endif
.PHONY: dummy all runtest clean superclean
dummy : all runtest
# test applications
ifneq (1, $(USE_EXTERNAL_CRYPTO))
AES_CALC = test/aes_calc$(EXE)
SHA1_DRIVER = test/sha1_driver$(EXE)
endif
testapp = test/cipher_driver$(EXE) test/datatypes_driver$(EXE) \
$(SHA1_DRIVER) test/kernel_driver$(EXE) \
$(AES_CALC) test/env$(EXE)
# data values used to test the aes_calc application for AES-128
k128=000102030405060708090a0b0c0d0e0f
p128=00112233445566778899aabbccddeeff
c128=69c4e0d86a7b0430d8cdb78070b4c55a
# data values used to test the aes_calc application for AES-256
k256=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
p256=00112233445566778899aabbccddeeff
c256=8ea2b7ca516745bfeafc49904b496089
runtest: $(testapp)
$(FIND_LIBRARIES) test/env$(EXE) # print out information on the build environment
@echo "running crypto test applications..."
ifneq (1, $(USE_EXTERNAL_CRYPTO))
$(FIND_LIBRARIES) test `test/aes_calc $(k128) $(p128)` = $(c128)
$(FIND_LIBRARIES) test `test/aes_calc $(k256) $(p256)` = $(c256)
$(FIND_LIBRARIES) test/sha1_driver$(EXE) -v >/dev/null
endif
$(FIND_LIBRARIES) test/cipher_driver$(EXE) -v >/dev/null
$(FIND_LIBRARIES) test/datatypes_driver$(EXE) -v >/dev/null
$(FIND_LIBRARIES) test/kernel_driver$(EXE) -v >/dev/null
@echo "crypto test applications passed."
# the rule for making object files and test apps
%.o: %.c
$(COMPILE) -c $< -o $@
%$(EXE): %.c $(srcdir)/../test/getopt_s.c
$(COMPILE) $(LDFLAGS) $< $(srcdir)/../test/getopt_s.c -o $@ $(CRYPTOLIB) $(LIBS)
all: $(testapp)
# housekeeping functions
clean:
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
superclean: clean
rm -f *core TAGS ktrace.out
# EOF

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,442 @@
/*
* aes_gcm_mbedtls.c
*
* AES Galois Counter Mode
*
* YongCheng Yang
*
*/
/*
*
* Copyright (c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <mbedtls/gcm.h>
#include "aes_gcm.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#include "crypto_types.h"
#include "cipher_types.h"
#include "cipher_test_cases.h"
srtp_debug_module_t srtp_mod_aes_gcm = {
false, /* debugging is off by default */
"aes gcm mbedtls" /* printable module name */
};
/**
* SRTP IV Formation for AES-GCM
* https://tools.ietf.org/html/rfc7714#section-8.1
* 0 0 0 0 0 0 0 0 0 0 1 1
* 0 1 2 3 4 5 6 7 8 9 0 1
* +--+--+--+--+--+--+--+--+--+--+--+--+
* |00|00| SSRC | ROC | SEQ |---+
* +--+--+--+--+--+--+--+--+--+--+--+--+ |
* |
* +--+--+--+--+--+--+--+--+--+--+--+--+ |
* | Encryption Salt |->(+)
* +--+--+--+--+--+--+--+--+--+--+--+--+ |
* |
* +--+--+--+--+--+--+--+--+--+--+--+--+ |
* | Initialization Vector |<--+
* +--+--+--+--+--+--+--+--+--+--+--+--+
*
* SRTCP IV Formation for AES-GCM
* https://tools.ietf.org/html/rfc7714#section-9.1
*
*/
/*
* 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_IV_LEN 12
#define GCM_AUTH_TAG_LEN 16
#define GCM_AUTH_TAG_LEN_8 8
#define FUNC_ENTRY() debug_print(srtp_mod_aes_gcm, "%s entry", __func__);
/*
* static function declarations.
*/
static srtp_err_status_t srtp_aes_gcm_mbedtls_alloc(srtp_cipher_t **c,
size_t key_len,
size_t tlen);
static srtp_err_status_t srtp_aes_gcm_mbedtls_dealloc(srtp_cipher_t *c);
static srtp_err_status_t srtp_aes_gcm_mbedtls_context_init(void *cv,
const uint8_t *key);
static srtp_err_status_t srtp_aes_gcm_mbedtls_set_iv(
void *cv,
uint8_t *iv,
srtp_cipher_direction_t direction);
static srtp_err_status_t srtp_aes_gcm_mbedtls_set_aad(void *cv,
const uint8_t *aad,
size_t aad_len);
static srtp_err_status_t srtp_aes_gcm_mbedtls_encrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len);
static srtp_err_status_t srtp_aes_gcm_mbedtls_decrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len);
/*
* Name of this crypto engine
*/
static const char srtp_aes_gcm_128_mbedtls_description[] =
"AES-128 GCM using mbedtls";
static const char srtp_aes_gcm_256_mbedtls_description[] =
"AES-256 GCM using mbedtls";
/*
* This is the vector function table for this crypto engine.
*/
/* clang-format off */
const srtp_cipher_type_t srtp_aes_gcm_128 = {
srtp_aes_gcm_mbedtls_alloc,
srtp_aes_gcm_mbedtls_dealloc,
srtp_aes_gcm_mbedtls_context_init,
srtp_aes_gcm_mbedtls_set_aad,
srtp_aes_gcm_mbedtls_encrypt,
srtp_aes_gcm_mbedtls_decrypt,
srtp_aes_gcm_mbedtls_set_iv,
srtp_aes_gcm_128_mbedtls_description,
&srtp_aes_gcm_128_test_case_0,
SRTP_AES_GCM_128
};
/* clang-format on */
/*
* This is the vector function table for this crypto engine.
*/
/* clang-format off */
const srtp_cipher_type_t srtp_aes_gcm_256 = {
srtp_aes_gcm_mbedtls_alloc,
srtp_aes_gcm_mbedtls_dealloc,
srtp_aes_gcm_mbedtls_context_init,
srtp_aes_gcm_mbedtls_set_aad,
srtp_aes_gcm_mbedtls_encrypt,
srtp_aes_gcm_mbedtls_decrypt,
srtp_aes_gcm_mbedtls_set_iv,
srtp_aes_gcm_256_mbedtls_description,
&srtp_aes_gcm_256_test_case_0,
SRTP_AES_GCM_256
};
/* clang-format on */
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 28 or 44 for
* AES-128-GCM or AES-256-GCM respectively. Note that the
* key length includes the 14 byte salt value that is used when
* initializing the KDF.
*/
static srtp_err_status_t srtp_aes_gcm_mbedtls_alloc(srtp_cipher_t **c,
size_t key_len,
size_t tlen)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *gcm;
debug_print(srtp_mod_aes_gcm, "allocating cipher with key length %zu",
key_len);
debug_print(srtp_mod_aes_gcm, "allocating cipher with tag length %zu",
tlen);
/*
* Verify the key_len is valid for one of: AES-128/256
*/
if (key_len != SRTP_AES_GCM_128_KEY_LEN_WSALT &&
key_len != SRTP_AES_GCM_256_KEY_LEN_WSALT) {
return (srtp_err_status_bad_param);
}
if (tlen != GCM_AUTH_TAG_LEN && tlen != GCM_AUTH_TAG_LEN_8) {
return (srtp_err_status_bad_param);
}
/* allocate memory a cipher of type aes_gcm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
return (srtp_err_status_alloc_fail);
}
gcm = (srtp_aes_gcm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_gcm_ctx_t));
if (gcm == NULL) {
srtp_crypto_free(*c);
*c = NULL;
return (srtp_err_status_alloc_fail);
}
gcm->ctx =
(mbedtls_gcm_context *)srtp_crypto_alloc(sizeof(mbedtls_gcm_context));
if (gcm->ctx == NULL) {
srtp_crypto_free(gcm);
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
mbedtls_gcm_init(gcm->ctx);
/* set pointers */
(*c)->state = gcm;
/* setup cipher attributes */
switch (key_len) {
case SRTP_AES_GCM_128_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_128;
(*c)->algorithm = SRTP_AES_GCM_128;
gcm->key_size = SRTP_AES_128_KEY_LEN;
gcm->tag_len = tlen;
break;
case SRTP_AES_GCM_256_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_256;
(*c)->algorithm = SRTP_AES_GCM_256;
gcm->key_size = SRTP_AES_256_KEY_LEN;
gcm->tag_len = tlen;
break;
}
/* set key size */
(*c)->key_len = key_len;
return (srtp_err_status_ok);
}
/*
* This function deallocates a GCM session
*/
static srtp_err_status_t srtp_aes_gcm_mbedtls_dealloc(srtp_cipher_t *c)
{
srtp_aes_gcm_ctx_t *ctx;
FUNC_ENTRY();
ctx = (srtp_aes_gcm_ctx_t *)c->state;
if (ctx) {
mbedtls_gcm_free(ctx->ctx);
srtp_crypto_free(ctx->ctx);
/* zeroize the key material */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_gcm_ctx_t));
srtp_crypto_free(ctx);
}
/* free memory */
srtp_crypto_free(c);
return (srtp_err_status_ok);
}
static srtp_err_status_t srtp_aes_gcm_mbedtls_context_init(void *cv,
const uint8_t *key)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
uint32_t key_len_in_bits;
int errCode = 0;
c->dir = srtp_direction_any;
c->aad_size = 0;
debug_print(srtp_mod_aes_gcm, "key: %s",
srtp_octet_string_hex_string(key, c->key_size));
key_len_in_bits = (c->key_size << 3);
switch (c->key_size) {
case SRTP_AES_256_KEY_LEN:
case SRTP_AES_128_KEY_LEN:
break;
default:
return (srtp_err_status_bad_param);
break;
}
errCode =
mbedtls_gcm_setkey(c->ctx, MBEDTLS_CIPHER_ID_AES, key, key_len_in_bits);
if (errCode != 0) {
debug_print(srtp_mod_aes_gcm, "mbedtls error code: %d", errCode);
return srtp_err_status_init_fail;
}
return (srtp_err_status_ok);
}
static srtp_err_status_t srtp_aes_gcm_mbedtls_set_iv(
void *cv,
uint8_t *iv,
srtp_cipher_direction_t direction)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
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",
srtp_octet_string_hex_string(iv, GCM_IV_LEN));
c->iv_len = GCM_IV_LEN;
memcpy(c->iv, iv, c->iv_len);
return (srtp_err_status_ok);
}
/*
* This function processes the AAD
*
* Parameters:
* c Crypto context
* aad Additional data to process for AEAD cipher suites
* aad_len length of aad buffer
*/
static srtp_err_status_t srtp_aes_gcm_mbedtls_set_aad(void *cv,
const uint8_t *aad,
size_t aad_len)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
debug_print(srtp_mod_aes_gcm, "setting AAD: %s",
srtp_octet_string_hex_string(aad, aad_len));
if (aad_len + c->aad_size > MAX_AD_SIZE) {
return srtp_err_status_bad_param;
}
memcpy(c->aad + c->aad_size, aad, aad_len);
c->aad_size += aad_len;
return (srtp_err_status_ok);
}
/*
* This function encrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_mbedtls_encrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
int errCode = 0;
if (c->dir != srtp_direction_encrypt) {
return srtp_err_status_bad_param;
}
if (*dst_len < src_len + c->tag_len) {
return srtp_err_status_buffer_small;
}
errCode = mbedtls_gcm_crypt_and_tag(c->ctx, MBEDTLS_GCM_ENCRYPT, src_len,
c->iv, c->iv_len, c->aad, c->aad_size,
src, dst, c->tag_len, dst + src_len);
c->aad_size = 0;
if (errCode != 0) {
debug_print(srtp_mod_aes_gcm, "mbedtls error code: %d", errCode);
return srtp_err_status_bad_param;
}
*dst_len = src_len + c->tag_len;
return srtp_err_status_ok;
}
/*
* This function decrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_mbedtls_decrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
int errCode = 0;
if (c->dir != srtp_direction_decrypt) {
return srtp_err_status_bad_param;
}
if (src_len < c->tag_len) {
return srtp_err_status_bad_param;
}
if (*dst_len < (src_len - c->tag_len)) {
return srtp_err_status_buffer_small;
}
debug_print(srtp_mod_aes_gcm, "AAD: %s",
srtp_octet_string_hex_string(c->aad, c->aad_size));
errCode = mbedtls_gcm_auth_decrypt(
c->ctx, (src_len - c->tag_len), c->iv, c->iv_len, c->aad, c->aad_size,
src + (src_len - c->tag_len), c->tag_len, src, dst);
c->aad_size = 0;
if (errCode != 0) {
return srtp_err_status_auth_fail;
}
/*
* Reduce the buffer size by the tag length since the tag
* is not part of the original payload
*/
*dst_len = (src_len - c->tag_len);
return srtp_err_status_ok;
}

View File

@@ -0,0 +1,431 @@
/*
* aes_gcm_nss.c
*
* AES Galois Counter Mode
*
* Richard L. Barnes
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "aes_gcm.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#include "crypto_types.h"
#include "cipher_types.h"
#include "cipher_test_cases.h"
#include <secerr.h>
#include <nspr.h>
srtp_debug_module_t srtp_mod_aes_gcm = {
false, /* debugging is off by default */
"aes gcm nss" /* printable module name */
};
/*
* 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_IV_LEN 12
#define GCM_AUTH_TAG_LEN 16
#define GCM_AUTH_TAG_LEN_8 8
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 28 or 44 for
* AES-128-GCM or AES-256-GCM respectively. Note that the
* key length includes the 14 byte salt value that is used when
* initializing the KDF.
*/
static srtp_err_status_t srtp_aes_gcm_nss_alloc(srtp_cipher_t **c,
size_t key_len,
size_t tlen)
{
srtp_aes_gcm_ctx_t *gcm;
NSSInitContext *nss;
debug_print(srtp_mod_aes_gcm, "allocating cipher with key length %zu",
key_len);
debug_print(srtp_mod_aes_gcm, "allocating cipher with tag length %zu",
tlen);
/*
* Verify the key_len is valid for one of: AES-128/256
*/
if (key_len != SRTP_AES_GCM_128_KEY_LEN_WSALT &&
key_len != SRTP_AES_GCM_256_KEY_LEN_WSALT) {
return (srtp_err_status_bad_param);
}
if (tlen != GCM_AUTH_TAG_LEN && tlen != GCM_AUTH_TAG_LEN_8) {
return (srtp_err_status_bad_param);
}
/* Initialize NSS equiv of NSS_NoDB_Init(NULL) */
nss = NSS_InitContext("", "", "", "", NULL,
NSS_INIT_READONLY | NSS_INIT_NOCERTDB |
NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN |
NSS_INIT_OPTIMIZESPACE);
if (!nss) {
return (srtp_err_status_cipher_fail);
}
/* allocate memory a cipher of type aes_gcm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
NSS_ShutdownContext(nss);
return (srtp_err_status_alloc_fail);
}
gcm = (srtp_aes_gcm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_gcm_ctx_t));
if (gcm == NULL) {
NSS_ShutdownContext(nss);
srtp_crypto_free(*c);
*c = NULL;
return (srtp_err_status_alloc_fail);
}
gcm->nss = nss;
/* set pointers */
(*c)->state = gcm;
/* setup cipher attributes */
switch (key_len) {
case SRTP_AES_GCM_128_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_128;
(*c)->algorithm = SRTP_AES_GCM_128;
gcm->key_size = SRTP_AES_128_KEY_LEN;
gcm->tag_size = tlen;
gcm->params.ulTagBits = 8 * tlen;
break;
case SRTP_AES_GCM_256_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_256;
(*c)->algorithm = SRTP_AES_GCM_256;
gcm->key_size = SRTP_AES_256_KEY_LEN;
gcm->tag_size = tlen;
gcm->params.ulTagBits = 8 * tlen;
break;
default:
/* this should never hit, but to be sure... */
return (srtp_err_status_bad_param);
}
/* set key size and tag size*/
(*c)->key_len = key_len;
return (srtp_err_status_ok);
}
/*
* This function deallocates a GCM session
*/
static srtp_err_status_t srtp_aes_gcm_nss_dealloc(srtp_cipher_t *c)
{
srtp_aes_gcm_ctx_t *ctx;
ctx = (srtp_aes_gcm_ctx_t *)c->state;
if (ctx) {
/* release NSS resources */
if (ctx->key) {
PK11_FreeSymKey(ctx->key);
}
if (ctx->nss) {
NSS_ShutdownContext(ctx->nss);
ctx->nss = NULL;
}
/* zeroize the key material */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_gcm_ctx_t));
srtp_crypto_free(ctx);
}
/* free memory */
srtp_crypto_free(c);
return (srtp_err_status_ok);
}
/*
* aes_gcm_nss_context_init(...) initializes the aes_gcm_context
* using the value in key[].
*
* the key is the secret key
*/
static srtp_err_status_t srtp_aes_gcm_nss_context_init(void *cv,
const uint8_t *key)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
c->dir = srtp_direction_any;
debug_print(srtp_mod_aes_gcm, "key: %s",
srtp_octet_string_hex_string(key, c->key_size));
if (c->key) {
PK11_FreeSymKey(c->key);
c->key = NULL;
}
PK11SlotInfo *slot = PK11_GetBestSlot(CKM_AES_GCM, NULL);
if (!slot) {
return (srtp_err_status_cipher_fail);
}
/* explicitly cast away const of key */
SECItem key_item = { siBuffer, (unsigned char *)(uintptr_t)key,
c->key_size };
c->key = PK11_ImportSymKey(slot, CKM_AES_GCM, PK11_OriginUnwrap,
CKA_ENCRYPT, &key_item, NULL);
PK11_FreeSlot(slot);
if (!c->key) {
return (srtp_err_status_cipher_fail);
}
return (srtp_err_status_ok);
}
/*
* aes_gcm_nss_set_iv(c, iv) sets the counter value to the exor of iv with
* the offset
*/
static srtp_err_status_t srtp_aes_gcm_nss_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) {
return (srtp_err_status_bad_param);
}
c->dir = direction;
debug_print(srtp_mod_aes_gcm, "setting iv: %s",
srtp_octet_string_hex_string(iv, GCM_IV_LEN));
memcpy(c->iv, iv, GCM_IV_LEN);
return (srtp_err_status_ok);
}
/*
* This function processes the AAD
*
* Parameters:
* c Crypto context
* aad Additional data to process for AEAD cipher suites
* aad_len length of aad buffer
*/
static srtp_err_status_t srtp_aes_gcm_nss_set_aad(void *cv,
const uint8_t *aad,
size_t aad_len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
debug_print(srtp_mod_aes_gcm, "setting AAD: %s",
srtp_octet_string_hex_string(aad, aad_len));
if (aad_len + c->aad_size > MAX_AD_SIZE) {
return srtp_err_status_bad_param;
}
memcpy(c->aad + c->aad_size, aad, aad_len);
c->aad_size += aad_len;
return (srtp_err_status_ok);
}
static srtp_err_status_t srtp_aes_gcm_nss_do_crypto(void *cv,
bool encrypt,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
c->params.pIv = c->iv;
c->params.ulIvLen = GCM_IV_LEN;
c->params.pAAD = c->aad;
c->params.ulAADLen = c->aad_size;
// Reset AAD
c->aad_size = 0;
unsigned int out_len = 0;
int rv;
SECItem param = { siBuffer, (unsigned char *)&c->params,
sizeof(CK_GCM_PARAMS) };
if (encrypt) {
if (c->dir != srtp_direction_encrypt) {
return srtp_err_status_bad_param;
}
if (*dst_len < src_len + c->tag_size) {
return srtp_err_status_buffer_small;
}
rv = PK11_Encrypt(c->key, CKM_AES_GCM, &param, dst, &out_len, *dst_len,
src, src_len);
} else {
if (c->dir != srtp_direction_decrypt) {
return srtp_err_status_bad_param;
}
if (src_len < c->tag_size) {
return srtp_err_status_bad_param;
}
if (*dst_len < src_len - c->tag_size) {
return srtp_err_status_buffer_small;
}
rv = PK11_Decrypt(c->key, CKM_AES_GCM, &param, dst, &out_len, *dst_len,
src, src_len);
}
*dst_len = out_len;
srtp_err_status_t status = srtp_err_status_ok;
if (rv != SECSuccess) {
status = srtp_err_status_cipher_fail;
}
return status;
}
/*
* This function encrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_nss_encrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
return srtp_aes_gcm_nss_do_crypto(cv, true, src, src_len, dst, dst_len);
}
/*
* This function decrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_nss_decrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
uint8_t tagbuf[16];
uint8_t *non_null_dst_buf = dst;
if (!non_null_dst_buf && (*dst_len == 0)) {
non_null_dst_buf = tagbuf;
*dst_len = sizeof(tagbuf);
} else if (!non_null_dst_buf) {
return srtp_err_status_bad_param;
}
srtp_err_status_t status = srtp_aes_gcm_nss_do_crypto(
cv, false, src, src_len, non_null_dst_buf, dst_len);
if (status != srtp_err_status_ok) {
int err = PR_GetError();
if (err == SEC_ERROR_BAD_DATA) {
status = srtp_err_status_auth_fail;
}
}
return status;
}
/*
* Name of this crypto engine
*/
static const char srtp_aes_gcm_128_nss_description[] = "AES-128 GCM using NSS";
static const char srtp_aes_gcm_256_nss_description[] = "AES-256 GCM using NSS";
/*
* This is the vector function table for this crypto engine.
*/
/* clang-format off */
const srtp_cipher_type_t srtp_aes_gcm_128 = {
srtp_aes_gcm_nss_alloc,
srtp_aes_gcm_nss_dealloc,
srtp_aes_gcm_nss_context_init,
srtp_aes_gcm_nss_set_aad,
srtp_aes_gcm_nss_encrypt,
srtp_aes_gcm_nss_decrypt,
srtp_aes_gcm_nss_set_iv,
srtp_aes_gcm_128_nss_description,
&srtp_aes_gcm_128_test_case_0,
SRTP_AES_GCM_128
};
/* clang-format on */
/*
* This is the vector function table for this crypto engine.
*/
/* clang-format off */
const srtp_cipher_type_t srtp_aes_gcm_256 = {
srtp_aes_gcm_nss_alloc,
srtp_aes_gcm_nss_dealloc,
srtp_aes_gcm_nss_context_init,
srtp_aes_gcm_nss_set_aad,
srtp_aes_gcm_nss_encrypt,
srtp_aes_gcm_nss_decrypt,
srtp_aes_gcm_nss_set_iv,
srtp_aes_gcm_256_nss_description,
&srtp_aes_gcm_256_test_case_0,
SRTP_AES_GCM_256
};
/* clang-format on */

View File

@@ -0,0 +1,433 @@
/*
* aes_gcm_ossl.c
*
* AES Galois Counter Mode
*
* John A. Foley
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <openssl/evp.h>
#include "aes_gcm.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#include "crypto_types.h"
#include "cipher_types.h"
#include "cipher_test_cases.h"
srtp_debug_module_t srtp_mod_aes_gcm = {
false, /* debugging is off by default */
"aes gcm" /* printable module name */
};
/*
* 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
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 28 or 44 for
* AES-128-GCM or AES-256-GCM respectively. Note that the
* 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,
size_t key_len,
size_t tlen)
{
srtp_aes_gcm_ctx_t *gcm;
debug_print(srtp_mod_aes_gcm, "allocating cipher with key length %zu",
key_len);
debug_print(srtp_mod_aes_gcm, "allocating cipher with tag length %zu",
tlen);
/*
* Verify the key_len is valid for one of: AES-128/256
*/
if (key_len != SRTP_AES_GCM_128_KEY_LEN_WSALT &&
key_len != SRTP_AES_GCM_256_KEY_LEN_WSALT) {
return (srtp_err_status_bad_param);
}
if (tlen != GCM_AUTH_TAG_LEN && tlen != GCM_AUTH_TAG_LEN_8) {
return (srtp_err_status_bad_param);
}
/* allocate memory a cipher of type aes_gcm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
return (srtp_err_status_alloc_fail);
}
gcm = (srtp_aes_gcm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_gcm_ctx_t));
if (gcm == NULL) {
srtp_crypto_free(*c);
*c = NULL;
return (srtp_err_status_alloc_fail);
}
gcm->ctx = EVP_CIPHER_CTX_new();
if (gcm->ctx == NULL) {
srtp_crypto_free(gcm);
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
/* set pointers */
(*c)->state = gcm;
/* setup cipher attributes */
switch (key_len) {
case SRTP_AES_GCM_128_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_128;
(*c)->algorithm = SRTP_AES_GCM_128;
gcm->key_size = SRTP_AES_128_KEY_LEN;
gcm->tag_len = tlen;
break;
case SRTP_AES_GCM_256_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_256;
(*c)->algorithm = SRTP_AES_GCM_256;
gcm->key_size = SRTP_AES_256_KEY_LEN;
gcm->tag_len = tlen;
break;
}
/* set key size */
(*c)->key_len = key_len;
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)
{
srtp_aes_gcm_ctx_t *ctx;
ctx = (srtp_aes_gcm_ctx_t *)c->state;
if (ctx) {
EVP_CIPHER_CTX_free(ctx->ctx);
/* zeroize the key material */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_gcm_ctx_t));
srtp_crypto_free(ctx);
}
/* free memory */
srtp_crypto_free(c);
return (srtp_err_status_ok);
}
/*
* aes_gcm_openssl_context_init(...) initializes the aes_gcm_context
* using the value in key[].
*
* the key is the secret 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));
switch (c->key_size) {
case SRTP_AES_256_KEY_LEN:
evp = EVP_aes_256_gcm();
break;
case SRTP_AES_128_KEY_LEN:
evp = EVP_aes_128_gcm();
break;
default:
return (srtp_err_status_bad_param);
break;
}
EVP_CIPHER_CTX_reset(c->ctx);
if (!EVP_CipherInit_ex(c->ctx, evp, NULL, key, NULL, 0)) {
return srtp_err_status_init_fail;
}
if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) {
return srtp_err_status_init_fail;
}
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)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
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",
srtp_octet_string_hex_string(iv, 12));
if (c->dir == srtp_direction_encrypt) {
if (EVP_EncryptInit_ex(c->ctx, NULL, NULL, NULL, iv) != 1) {
return srtp_err_status_init_fail;
}
} else {
if (EVP_DecryptInit_ex(c->ctx, NULL, NULL, NULL, iv) != 1) {
return srtp_err_status_init_fail;
}
}
return srtp_err_status_ok;
}
/*
* This function processes the AAD
*
* Parameters:
* c Crypto context
* 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,
size_t aad_len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
int len = 0;
debug_print(srtp_mod_aes_gcm, "setting AAD: %s",
srtp_octet_string_hex_string(aad, aad_len));
if (c->dir == srtp_direction_encrypt) {
if (EVP_EncryptUpdate(c->ctx, NULL, &len, aad, (int)aad_len) != 1) {
return srtp_err_status_algo_fail;
}
} else {
if (EVP_DecryptUpdate(c->ctx, NULL, &len, aad, (int)aad_len) != 1) {
return srtp_err_status_algo_fail;
}
}
if (len != (int)aad_len) {
return srtp_err_status_algo_fail;
}
return srtp_err_status_ok;
}
/*
* This function encrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_openssl_encrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
int len = 0;
if (c->dir != srtp_direction_encrypt) {
return srtp_err_status_bad_param;
}
if (*dst_len < src_len + c->tag_len) {
return srtp_err_status_buffer_small;
}
/*
* Encrypt the data
*/
if (EVP_EncryptUpdate(c->ctx, dst, &len, src, (int)src_len) != 1) {
return srtp_err_status_algo_fail;
}
*dst_len = len;
/*
* Calculate the tag
*/
if (EVP_EncryptFinal_ex(c->ctx, dst + len, &len) != 1) {
return srtp_err_status_algo_fail;
}
*dst_len += len;
/*
* Retrieve the tag
*/
if (EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_GET_TAG, (int)c->tag_len,
dst + *dst_len) != 1) {
return srtp_err_status_algo_fail;
}
*dst_len += c->tag_len;
return srtp_err_status_ok;
}
/*
* This function decrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_openssl_decrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
int len = 0;
if (c->dir != srtp_direction_decrypt) {
return srtp_err_status_bad_param;
}
if (src_len < c->tag_len) {
return srtp_err_status_bad_param;
}
if (*dst_len < src_len - c->tag_len) {
return srtp_err_status_buffer_small;
}
/*
* Decrypt the data
*/
if (EVP_DecryptUpdate(c->ctx, dst, &len, src,
(int)(src_len - c->tag_len)) != 1) {
return srtp_err_status_algo_fail;
}
*dst_len = len;
/*
* Set the tag before decrypting
*
* explicitly cast away const of src
*/
if (EVP_CIPHER_CTX_ctrl(
c->ctx, EVP_CTRL_GCM_SET_TAG, (int)c->tag_len,
(void *)(uintptr_t)(src + (src_len - c->tag_len))) != 1) {
return srtp_err_status_algo_fail;
}
/*
* Check the tag
*/
if (EVP_DecryptFinal_ex(c->ctx, dst + *dst_len, &len) != 1) {
return srtp_err_status_auth_fail;
}
*dst_len += len;
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";
/*
* This is the vector function table for this crypto engine.
*/
/* clang-format off */
const srtp_cipher_type_t srtp_aes_gcm_128 = {
srtp_aes_gcm_openssl_alloc,
srtp_aes_gcm_openssl_dealloc,
srtp_aes_gcm_openssl_context_init,
srtp_aes_gcm_openssl_set_aad,
srtp_aes_gcm_openssl_encrypt,
srtp_aes_gcm_openssl_decrypt,
srtp_aes_gcm_openssl_set_iv,
srtp_aes_gcm_128_openssl_description,
&srtp_aes_gcm_128_test_case_0,
SRTP_AES_GCM_128
};
/* clang-format on */
/*
* This is the vector function table for this crypto engine.
*/
/* clang-format off */
const srtp_cipher_type_t srtp_aes_gcm_256 = {
srtp_aes_gcm_openssl_alloc,
srtp_aes_gcm_openssl_dealloc,
srtp_aes_gcm_openssl_context_init,
srtp_aes_gcm_openssl_set_aad,
srtp_aes_gcm_openssl_encrypt,
srtp_aes_gcm_openssl_decrypt,
srtp_aes_gcm_openssl_set_iv,
srtp_aes_gcm_256_openssl_description,
&srtp_aes_gcm_256_test_case_0,
SRTP_AES_GCM_256
};
/* clang-format on */

View File

@@ -0,0 +1,474 @@
/*
* aes_gcm_wssl.c
*
* AES Galois Counter Mode using wolfSSL
*
* Sean Parkinson, wolfSSL
*
*/
/*
*
* Copyright (c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/aes.h>
#include "aes_gcm.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#include "crypto_types.h"
#include "cipher_types.h"
#include "cipher_test_cases.h"
srtp_debug_module_t srtp_mod_aes_gcm = {
0, /* debugging is off by default */
"aes gcm wssl" /* printable module name */
};
/**
* SRTP IV Formation for AES-GCM
* https://tools.ietf.org/html/rfc7714#section-8.1
* 0 0 0 0 0 0 0 0 0 0 1 1
* 0 1 2 3 4 5 6 7 8 9 0 1
* +--+--+--+--+--+--+--+--+--+--+--+--+
* |00|00| SSRC | ROC | SEQ |---+
* +--+--+--+--+--+--+--+--+--+--+--+--+ |
* |
* +--+--+--+--+--+--+--+--+--+--+--+--+ |
* | Encryption Salt |->(+)
* +--+--+--+--+--+--+--+--+--+--+--+--+ |
* |
* +--+--+--+--+--+--+--+--+--+--+--+--+ |
* | Initialization Vector |<--+
* +--+--+--+--+--+--+--+--+--+--+--+--+
*
* SRTCP IV Formation for AES-GCM
* https://tools.ietf.org/html/rfc7714#section-9.1
*
*/
/*
* 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 AES_BLOCK_SIZE
#define GCM_AUTH_TAG_LEN_8 8
#define FUNC_ENTRY() debug_print(srtp_mod_aes_gcm, "%s entry", __func__);
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 28 or 44 for
* AES-128-GCM or AES-256-GCM respectively. Note that the
* key length includes the 14 byte salt value that is used when
* initializing the KDF.
*/
static srtp_err_status_t srtp_aes_gcm_wolfssl_alloc(srtp_cipher_t **c,
size_t key_len,
size_t tlen)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *gcm;
debug_print(srtp_mod_aes_gcm, "allocating cipher with key length %zu",
key_len);
debug_print(srtp_mod_aes_gcm, "allocating cipher with tag length %zu",
tlen);
/*
* Verify the key_len is valid for one of: AES-128/256
*/
if (key_len != SRTP_AES_GCM_128_KEY_LEN_WSALT &&
key_len != SRTP_AES_GCM_256_KEY_LEN_WSALT) {
return (srtp_err_status_bad_param);
}
if (tlen != GCM_AUTH_TAG_LEN && tlen != GCM_AUTH_TAG_LEN_8) {
return (srtp_err_status_bad_param);
}
/* allocate memory a cipher of type aes_gcm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
return (srtp_err_status_alloc_fail);
}
gcm = (srtp_aes_gcm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_gcm_ctx_t));
if (gcm == NULL) {
srtp_crypto_free(*c);
*c = NULL;
return (srtp_err_status_alloc_fail);
}
gcm->ctx = NULL;
/* set pointers */
(*c)->state = gcm;
/* setup cipher attributes */
switch (key_len) {
case SRTP_AES_GCM_128_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_128;
(*c)->algorithm = SRTP_AES_GCM_128;
gcm->key_size = SRTP_AES_128_KEY_LEN;
gcm->tag_len = tlen;
break;
case SRTP_AES_GCM_256_KEY_LEN_WSALT:
(*c)->type = &srtp_aes_gcm_256;
(*c)->algorithm = SRTP_AES_GCM_256;
gcm->key_size = SRTP_AES_256_KEY_LEN;
gcm->tag_len = tlen;
break;
}
/* set key size */
(*c)->key_len = key_len;
return (srtp_err_status_ok);
}
/*
* This function deallocates a GCM session
*/
static srtp_err_status_t srtp_aes_gcm_wolfssl_dealloc(srtp_cipher_t *c)
{
srtp_aes_gcm_ctx_t *ctx;
FUNC_ENTRY();
ctx = (srtp_aes_gcm_ctx_t *)c->state;
if (ctx != NULL) {
if (ctx->ctx != NULL) {
wc_AesFree(ctx->ctx);
srtp_crypto_free(ctx->ctx);
}
/* zeroize the key material */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_gcm_ctx_t));
srtp_crypto_free(ctx);
}
/* free memory */
srtp_crypto_free(c);
return (srtp_err_status_ok);
}
static srtp_err_status_t srtp_aes_gcm_wolfssl_context_init(void *cv,
const uint8_t *key)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
int err;
c->dir = srtp_direction_any;
#ifndef WOLFSSL_AESGCM_STREAM
c->aad_size = 0;
#endif
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:
case SRTP_AES_128_KEY_LEN:
break;
default:
return (srtp_err_status_bad_param);
break;
}
if (c->ctx == NULL) {
c->ctx = (Aes *)srtp_crypto_alloc(sizeof(Aes));
if (c->ctx == NULL) {
return srtp_err_status_alloc_fail;
}
err = wc_AesInit(c->ctx, NULL, INVALID_DEVID);
if (err < 0) {
srtp_crypto_free(c->ctx);
c->ctx = NULL;
debug_print(srtp_mod_aes_gcm, "wolfSSL error code: %d", err);
return srtp_err_status_init_fail;
}
}
err = wc_AesGcmSetKey(c->ctx, (const unsigned char *)key, c->key_size);
if (err < 0) {
debug_print(srtp_mod_aes_gcm, "wolfSSL error code: %d", err);
return srtp_err_status_init_fail;
}
return (srtp_err_status_ok);
}
static srtp_err_status_t srtp_aes_gcm_wolfssl_set_iv(
void *cv,
uint8_t *iv,
srtp_cipher_direction_t direction)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
#ifdef WOLFSSL_AESGCM_STREAM
int err;
#endif
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",
srtp_octet_string_hex_string(iv, GCM_NONCE_MID_SZ));
#ifndef WOLFSSL_AESGCM_STREAM
c->iv_len = GCM_NONCE_MID_SZ;
memcpy(c->iv, iv, c->iv_len);
c->aad_size = 0;
#else
err = wc_AesGcmInit(c->ctx, NULL, 0, iv, GCM_NONCE_MID_SZ);
if (err < 0) {
debug_print(srtp_mod_aes_gcm, "wolfSSL error code: %d", err);
return srtp_err_status_init_fail;
}
#endif
return (srtp_err_status_ok);
}
/*
* This function processes the AAD
*
* Parameters:
* c Crypto context
* aad Additional data to process for AEAD cipher suites
* aad_len length of aad buffer
*/
static srtp_err_status_t srtp_aes_gcm_wolfssl_set_aad(void *cv,
const uint8_t *aad,
size_t aad_len)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
#ifdef WOLFSSL_AESGCM_STREAM
int err;
#endif
debug_print(srtp_mod_aes_gcm, "setting AAD: %s",
srtp_octet_string_hex_string(aad, aad_len));
#ifndef WOLFSSL_AESGCM_STREAM
if (aad_len + c->aad_size > MAX_AD_SIZE) {
return srtp_err_status_bad_param;
}
memcpy(c->aad + c->aad_size, aad, aad_len);
c->aad_size += aad_len;
#else
if (c->dir == srtp_direction_encrypt) {
err = wc_AesGcmEncryptUpdate(c->ctx, NULL, NULL, 0, aad, aad_len);
} else {
err = wc_AesGcmDecryptUpdate(c->ctx, NULL, NULL, 0, aad, aad_len);
}
if (err < 0) {
debug_print(srtp_mod_aes_gcm, "wolfSSL error code: %d", err);
return srtp_err_status_algo_fail;
}
#endif
return (srtp_err_status_ok);
}
/*
* This function encrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_wolfssl_encrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
int err;
if (c->dir != srtp_direction_encrypt) {
return srtp_err_status_bad_param;
}
if (*dst_len < src_len + c->tag_len) {
return srtp_err_status_buffer_small;
}
#ifndef WOLFSSL_AESGCM_STREAM
// tag must always be 16 bytes when passed to wc_AesGcmEncrypt, can truncate
// to c->tag_len after
uint8_t tag[GCM_AUTH_TAG_LEN];
err = wc_AesGcmEncrypt(c->ctx, dst, src, src_len, c->iv, c->iv_len, tag,
sizeof(tag), c->aad, c->aad_size);
c->aad_size = 0;
if (err == 0) {
memcpy(dst + src_len, tag, c->tag_len);
}
#else
err = wc_AesGcmEncryptUpdate(c->ctx, dst, src, src_len, NULL, 0);
if (err < 0) {
debug_print(srtp_mod_aes_gcm, "wolfSSL error code: %d", err);
return srtp_err_status_algo_fail;
}
err = wc_AesGcmEncryptFinal(c->ctx, dst + src_len, c->tag_len);
#endif
if (err < 0) {
debug_print(srtp_mod_aes_gcm, "wolfSSL error code: %d", err);
printf("wolfSSL error code: %d\n", err);
return srtp_err_status_algo_fail;
}
*dst_len = src_len + c->tag_len;
return srtp_err_status_ok;
}
/*
* This function decrypts a buffer using AES GCM mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_gcm_wolfssl_decrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
FUNC_ENTRY();
srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv;
int err;
if (c->dir != srtp_direction_decrypt) {
return srtp_err_status_bad_param;
}
if (src_len < c->tag_len) {
return srtp_err_status_bad_param;
}
if (*dst_len < src_len - c->tag_len) {
return srtp_err_status_buffer_small;
}
#ifndef WOLFSSL_AESGCM_STREAM
debug_print(srtp_mod_aes_gcm, "AAD: %s",
srtp_octet_string_hex_string(c->aad, c->aad_size));
err = wc_AesGcmDecrypt(c->ctx, dst, src, (src_len - c->tag_len), c->iv,
c->iv_len, src + (src_len - c->tag_len), c->tag_len,
c->aad, c->aad_size);
c->aad_size = 0;
#else
err = wc_AesGcmDecryptUpdate(c->ctx, dst, src, (src_len - c->tag_len), NULL,
0);
if (err < 0) {
debug_print(srtp_mod_aes_gcm, "wolfSSL error code: %d", err);
return srtp_err_status_algo_fail;
}
err =
wc_AesGcmDecryptFinal(c->ctx, src + (src_len - c->tag_len), c->tag_len);
#endif
if (err < 0) {
debug_print(srtp_mod_aes_gcm, "wolfSSL error code: %d", err);
return srtp_err_status_auth_fail;
}
/*
* Reduce the buffer size by the tag length since the tag
* is not part of the original payload
*/
*dst_len = src_len -= c->tag_len;
return srtp_err_status_ok;
}
/*
* Name of this crypto engine
*/
static const char srtp_aes_gcm_128_wolfssl_description[] =
"AES-128 GCM using wolfssl";
static const char srtp_aes_gcm_256_wolfssl_description[] =
"AES-256 GCM using wolfssl";
/*
* This is the vector function table for this crypto engine.
*/
/* clang-format off */
const srtp_cipher_type_t srtp_aes_gcm_128 = {
srtp_aes_gcm_wolfssl_alloc,
srtp_aes_gcm_wolfssl_dealloc,
srtp_aes_gcm_wolfssl_context_init,
srtp_aes_gcm_wolfssl_set_aad,
srtp_aes_gcm_wolfssl_encrypt,
srtp_aes_gcm_wolfssl_decrypt,
srtp_aes_gcm_wolfssl_set_iv,
srtp_aes_gcm_128_wolfssl_description,
&srtp_aes_gcm_128_test_case_0,
SRTP_AES_GCM_128
};
/* clang-format on */
/*
* This is the vector function table for this crypto engine.
*/
/* clang-format off */
const srtp_cipher_type_t srtp_aes_gcm_256 = {
srtp_aes_gcm_wolfssl_alloc,
srtp_aes_gcm_wolfssl_dealloc,
srtp_aes_gcm_wolfssl_context_init,
srtp_aes_gcm_wolfssl_set_aad,
srtp_aes_gcm_wolfssl_encrypt,
srtp_aes_gcm_wolfssl_decrypt,
srtp_aes_gcm_wolfssl_set_iv,
srtp_aes_gcm_256_wolfssl_description,
&srtp_aes_gcm_256_test_case_0,
SRTP_AES_GCM_256
};
/* clang-format on */

View File

@@ -0,0 +1,449 @@
/*
* aes_icm.c
*
* AES Integer Counter Mode
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define ALIGN_32 0
#include "aes_icm.h"
#include "alloc.h"
#include "cipher_types.h"
#include "cipher_test_cases.h"
srtp_debug_module_t srtp_mod_aes_icm = {
false, /* debugging is off by default */
"aes icm" /* printable module name */
};
/*
* integer counter mode works as follows:
*
* 16 bits
* <----->
* +------+------+------+------+------+------+------+------+
* | nonce | pakcet index | ctr |---+
* +------+------+------+------+------+------+------+------+ |
* |
* +------+------+------+------+------+------+------+------+ v
* | salt |000000|->(+)
* +------+------+------+------+------+------+------+------+ |
* |
* +---------+
* | encrypt |
* +---------+
* |
* +------+------+------+------+------+------+------+------+ |
* | keystream block |<--+
* +------+------+------+------+------+------+------+------+
*
* All fields are big-endian
*
* ctr is the block counter, which increments from zero for
* each packet (16 bits wide)
*
* packet index is distinct for each packet (48 bits wide)
*
* nonce can be distinct across many uses of the same key, or
* can be a fixed value per key, or can be per-packet randomness
* (64 bits)
*
*/
static srtp_err_status_t srtp_aes_icm_alloc(srtp_cipher_t **c,
size_t key_len,
size_t tlen)
{
srtp_aes_icm_ctx_t *icm;
(void)tlen;
debug_print(srtp_mod_aes_icm, "allocating cipher with key length %zu",
key_len);
/*
* The check for key_len = 30/46 does not apply. Our usage
* of aes functions with key_len = values other than 30
* 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) {
return srtp_err_status_bad_param;
}
/* allocate memory a cipher of type aes_icm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
return srtp_err_status_alloc_fail;
}
icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t));
if (icm == NULL) {
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
/* set pointers */
(*c)->state = icm;
switch (key_len) {
case SRTP_AES_ICM_256_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_256;
(*c)->type = &srtp_aes_icm_256;
break;
default:
(*c)->algorithm = SRTP_AES_ICM_128;
(*c)->type = &srtp_aes_icm_128;
break;
}
/* set key size */
icm->key_size = key_len;
(*c)->key_len = key_len;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_aes_icm_dealloc(srtp_cipher_t *c)
{
srtp_aes_icm_ctx_t *ctx;
if (c == NULL) {
return srtp_err_status_bad_param;
}
ctx = (srtp_aes_icm_ctx_t *)c->state;
if (ctx) {
/* zeroize the key material */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_icm_ctx_t));
srtp_crypto_free(ctx);
}
/* free the cipher context */
srtp_crypto_free(c);
return srtp_err_status_ok;
}
/*
* aes_icm_context_init(...) initializes the aes_icm_context
* using the value in key[].
*
* the key is the secret key
*
* 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_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;
size_t 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) {
base_key_len = c->key_size - SRTP_SALT_LEN;
} else {
return srtp_err_status_bad_param;
}
/*
* set counter and initial values to 'offset' value, being careful not to
* go past the end of the key buffer
*/
v128_set_to_zero(&c->counter);
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) */
if (copy_len > SRTP_SALT_LEN) {
copy_len = SRTP_SALT_LEN;
}
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));
/* expand 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);
return status;
}
/* indicate that the keystream_buffer is empty */
c->bytes_in_buffer = 0;
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_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;
(void)direction;
/* set nonce (for alignment) */
v128_copy_octet_string(&nonce, iv);
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));
/* indicate that the keystream_buffer is empty */
c->bytes_in_buffer = 0;
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)
{
/* fill buffer with new keystream */
v128_copy(&c->keystream_buffer, &c->counter);
srtp_aes_encrypt(&c->keystream_buffer, &c->expanded_key);
c->bytes_in_buffer = sizeof(v128_t);
debug_print(srtp_mod_aes_icm, "counter: %s",
v128_hex_string(&c->counter));
debug_print(srtp_mod_aes_icm, "ciphertext: %s",
v128_hex_string(&c->keystream_buffer));
/* clock counter forward */
if (!++(c->counter.v8[15])) {
++(c->counter.v8[14]);
}
}
/*
* icm_encrypt deals with the following cases:
*
* bytes_to_encr < bytes_in_buffer
* - add keystream into data
*
* bytes_to_encr > bytes_in_buffer
* - add keystream into data until keystream_buffer is depleted
* - loop over blocks, filling keystream_buffer and then
* adding keystream into data
* - fill buffer then add in remaining (< 16) bytes of keystream
*/
static srtp_err_status_t srtp_aes_icm_encrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
size_t bytes_to_encr = src_len;
uint32_t *b;
const uint32_t *s;
if (*dst_len < src_len) {
return srtp_err_status_buffer_small;
}
*dst_len = src_len;
unsigned char *buf = dst;
/* check that there's enough segment left*/
size_t bytes_of_new_keystream = bytes_to_encr - c->bytes_in_buffer;
size_t blocks_of_new_keystream = (bytes_of_new_keystream + 15) >> 4;
if ((blocks_of_new_keystream + htons(c->counter.v16[7])) > 0xffff) {
return srtp_err_status_terminus;
}
debug_print(srtp_mod_aes_icm, "block index: %d", htons(c->counter.v16[7]));
if (bytes_to_encr <= c->bytes_in_buffer) {
/* deal with odd case of small bytes_to_encr */
for (size_t i = (sizeof(v128_t) - c->bytes_in_buffer);
i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++) {
*buf++ = *src++ ^ c->keystream_buffer.v8[i];
}
c->bytes_in_buffer -= bytes_to_encr;
/* return now to avoid the main loop */
return srtp_err_status_ok;
} else {
/* encrypt bytes until the remaining data is 16-byte aligned */
for (size_t i = (sizeof(v128_t) - c->bytes_in_buffer);
i < sizeof(v128_t); i++) {
*buf++ = *src++ ^ 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 (size_t 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!)
*/
#if ALIGN_32
b = (uint32_t *)buf;
s = (const uint32_t *)src;
*b++ = *s++ ^ c->keystream_buffer.v32[0];
*b++ = *s++ ^ c->keystream_buffer.v32[1];
*b++ = *s++ ^ c->keystream_buffer.v32[2];
*b++ = *s++ ^ c->keystream_buffer.v32[3];
buf = (uint8_t *)b;
src = (const uint8_t *)s;
#else
if ((((uintptr_t)buf) & 0x03) != 0) {
*buf++ = *src++ ^ c->keystream_buffer.v8[0];
*buf++ = *src++ ^ c->keystream_buffer.v8[1];
*buf++ = *src++ ^ c->keystream_buffer.v8[2];
*buf++ = *src++ ^ c->keystream_buffer.v8[3];
*buf++ = *src++ ^ c->keystream_buffer.v8[4];
*buf++ = *src++ ^ c->keystream_buffer.v8[5];
*buf++ = *src++ ^ c->keystream_buffer.v8[6];
*buf++ = *src++ ^ c->keystream_buffer.v8[7];
*buf++ = *src++ ^ c->keystream_buffer.v8[8];
*buf++ = *src++ ^ c->keystream_buffer.v8[9];
*buf++ = *src++ ^ c->keystream_buffer.v8[10];
*buf++ = *src++ ^ c->keystream_buffer.v8[11];
*buf++ = *src++ ^ c->keystream_buffer.v8[12];
*buf++ = *src++ ^ c->keystream_buffer.v8[13];
*buf++ = *src++ ^ c->keystream_buffer.v8[14];
*buf++ = *src++ ^ c->keystream_buffer.v8[15];
} else {
b = (uint32_t *)buf;
s = (const uint32_t *)src;
*b++ = *s++ ^ c->keystream_buffer.v32[0];
*b++ = *s++ ^ c->keystream_buffer.v32[1];
*b++ = *s++ ^ c->keystream_buffer.v32[2];
*b++ = *s++ ^ c->keystream_buffer.v32[3];
buf = (uint8_t *)b;
src = (const uint8_t *)s;
}
#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);
for (size_t i = 0; i < (bytes_to_encr & 0xf); i++) {
*buf++ = *src++ ^ c->keystream_buffer.v8[i];
}
/* reset the keystream buffer size to right value */
c->bytes_in_buffer = sizeof(v128_t) - (bytes_to_encr & 0xf);
} 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";
/*
* 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, /* */
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, /* */
srtp_aes_icm_256_description, /* */
&srtp_aes_icm_256_test_case_0, /* */
SRTP_AES_ICM_256 /* */
};

View File

@@ -0,0 +1,402 @@
/*
* aes_icm_mbedtls.c
*
* AES Integer Counter Mode
*
* YongCheng Yang
*/
/*
*
* Copyright (c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <mbedtls/aes.h>
#include "aes_icm_ext.h"
#include "crypto_types.h"
#include "err.h" /* for srtp_debug */
#include "alloc.h"
#include "cipher_types.h"
#include "cipher_test_cases.h"
srtp_debug_module_t srtp_mod_aes_icm = {
false, /* debugging is off by default */
"aes icm mbedtls" /* printable module name */
};
/*
* static function declarations.
*/
static srtp_err_status_t srtp_aes_icm_mbedtls_alloc(srtp_cipher_t **c,
size_t key_len,
size_t tlen);
static srtp_err_status_t srtp_aes_icm_mbedtls_dealloc(srtp_cipher_t *c);
static srtp_err_status_t srtp_aes_icm_mbedtls_context_init(void *cv,
const uint8_t *key);
static srtp_err_status_t srtp_aes_icm_mbedtls_set_iv(
void *cv,
uint8_t *iv,
srtp_cipher_direction_t dir);
static srtp_err_status_t srtp_aes_icm_mbedtls_encrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len);
/*
* Name of this crypto engine
*/
static const char srtp_aes_icm_128_mbedtls_description[] =
"AES-128 counter mode using mbedtls";
static const char srtp_aes_icm_192_mbedtls_description[] =
"AES-192 counter mode using mbedtls";
static const char srtp_aes_icm_256_mbedtls_description[] =
"AES-256 counter mode using mbedtls";
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_128 = {
srtp_aes_icm_mbedtls_alloc, /* */
srtp_aes_icm_mbedtls_dealloc, /* */
srtp_aes_icm_mbedtls_context_init, /* */
0, /* set_aad */
srtp_aes_icm_mbedtls_encrypt, /* */
srtp_aes_icm_mbedtls_encrypt, /* */
srtp_aes_icm_mbedtls_set_iv, /* */
srtp_aes_icm_128_mbedtls_description, /* */
&srtp_aes_icm_128_test_case_0, /* */
SRTP_AES_ICM_128 /* */
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_192 = {
srtp_aes_icm_mbedtls_alloc, /* */
srtp_aes_icm_mbedtls_dealloc, /* */
srtp_aes_icm_mbedtls_context_init, /* */
0, /* set_aad */
srtp_aes_icm_mbedtls_encrypt, /* */
srtp_aes_icm_mbedtls_encrypt, /* */
srtp_aes_icm_mbedtls_set_iv, /* */
srtp_aes_icm_192_mbedtls_description, /* */
&srtp_aes_icm_192_test_case_0, /* */
SRTP_AES_ICM_192 /* */
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_256 = {
srtp_aes_icm_mbedtls_alloc, /* */
srtp_aes_icm_mbedtls_dealloc, /* */
srtp_aes_icm_mbedtls_context_init, /* */
0, /* set_aad */
srtp_aes_icm_mbedtls_encrypt, /* */
srtp_aes_icm_mbedtls_encrypt, /* */
srtp_aes_icm_mbedtls_set_iv, /* */
srtp_aes_icm_256_mbedtls_description, /* */
&srtp_aes_icm_256_test_case_0, /* */
SRTP_AES_ICM_256 /* */
};
/*
* integer counter mode works as follows:
*
* https://tools.ietf.org/html/rfc3711#section-4.1.1
*
* E(k, IV) || E(k, IV + 1 mod 2^128) || E(k, IV + 2 mod 2^128) ...
* IV = (k_s * 2^16) XOR (SSRC * 2^64) XOR (i * 2^16)
*
* IV SHALL be defined by the SSRC, the SRTP packet index i,
* and the SRTP session salting key k_s.
*
* SSRC: 32bits.
* Sequence number: 16bits.
* nonce is 64bits. .
* packet index = ROC || SEQ. (ROC: Rollover counter)
*
* 16 bits
* <----->
* +------+------+------+------+------+------+------+------+
* | nonce | packet index | ctr |---+
* +------+------+------+------+------+------+------+------+ |
* |
* +------+------+------+------+------+------+------+------+ v
* | salt |000000|->(+)
* +------+------+------+------+------+------+------+------+ |
* |
* +---------+
* | encrypt |
* +---------+
* |
* +------+------+------+------+------+------+------+------+ |
* | keystream block |<--+
* +------+------+------+------+------+------+------+------+
*
* All fields are big-endian
*
* ctr is the block counter, which increments from zero for
* each packet (16 bits wide)
*
* packet index is distinct for each packet (48 bits wide)
*
* nonce can be distinct across many uses of the same key, or
* can be a fixed value per key, or can be per-packet randomness
* (64 bits)
*
*/
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 30, 38, or 46 for
* AES-128, AES-192, and AES-256 respectively. Note, this key_len
* value is inflated, as it also accounts for the 112 bit salt
* 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_mbedtls_alloc(srtp_cipher_t **c,
size_t key_len,
size_t tlen)
{
srtp_aes_icm_ctx_t *icm;
(void)tlen;
debug_print(srtp_mod_aes_icm, "allocating cipher with key length %zu",
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 &&
key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) {
return srtp_err_status_bad_param;
}
/* allocate memory a cipher of type aes_icm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
return srtp_err_status_alloc_fail;
}
icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t));
if (icm == NULL) {
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
icm->ctx =
(mbedtls_aes_context *)srtp_crypto_alloc(sizeof(mbedtls_aes_context));
if (icm->ctx == NULL) {
srtp_crypto_free(icm);
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
mbedtls_aes_init(icm->ctx);
/* set pointers */
(*c)->state = icm;
/* setup cipher parameters */
switch (key_len) {
case SRTP_AES_ICM_128_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_128;
(*c)->type = &srtp_aes_icm_128;
icm->key_size = SRTP_AES_128_KEY_LEN;
break;
case SRTP_AES_ICM_192_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_192;
(*c)->type = &srtp_aes_icm_192;
icm->key_size = SRTP_AES_192_KEY_LEN;
break;
case SRTP_AES_ICM_256_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_256;
(*c)->type = &srtp_aes_icm_256;
icm->key_size = SRTP_AES_256_KEY_LEN;
break;
}
/* set key size */
(*c)->key_len = key_len;
return srtp_err_status_ok;
}
/*
* This function deallocates an instance of this engine
*/
static srtp_err_status_t srtp_aes_icm_mbedtls_dealloc(srtp_cipher_t *c)
{
srtp_aes_icm_ctx_t *ctx;
if (c == NULL) {
return srtp_err_status_bad_param;
}
/*
* Free the aes context
*/
ctx = (srtp_aes_icm_ctx_t *)c->state;
if (ctx != NULL) {
mbedtls_aes_free(ctx->ctx);
srtp_crypto_free(ctx->ctx);
/* zeroize the key material */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_icm_ctx_t));
srtp_crypto_free(ctx);
}
/* free memory */
srtp_crypto_free(c);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_aes_icm_mbedtls_context_init(void *cv,
const uint8_t *key)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
uint32_t key_size_in_bits = (c->key_size << 3);
int errcode = 0;
/*
* set counter and initial values to 'offset' value, being careful not to
* go past the end of the key buffer
*/
v128_set_to_zero(&c->counter);
v128_set_to_zero(&c->offset);
memcpy(&c->counter, key + c->key_size, SRTP_SALT_LEN);
memcpy(&c->offset, key + c->key_size, SRTP_SALT_LEN);
/* force last two octets of the offset to zero (for srtp compatibility) */
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, "offset: %s", v128_hex_string(&c->offset));
switch (c->key_size) {
case SRTP_AES_256_KEY_LEN:
case SRTP_AES_192_KEY_LEN:
case SRTP_AES_128_KEY_LEN:
break;
default:
return srtp_err_status_bad_param;
break;
}
errcode = mbedtls_aes_setkey_enc(c->ctx, key, key_size_in_bits);
if (errcode != 0) {
debug_print(srtp_mod_aes_icm, "errCode: %d", errcode);
}
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_mbedtls_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;
(void)dir;
c->nc_off = 0;
/* set nonce (for alignment) */
v128_copy_octet_string(&nonce, iv);
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));
return srtp_err_status_ok;
}
/*
* This function encrypts a buffer using AES CTR mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_icm_mbedtls_encrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
int errCode = 0;
debug_print(srtp_mod_aes_icm, "rs0: %s", v128_hex_string(&c->counter));
if (*dst_len < src_len) {
return srtp_err_status_buffer_small;
}
errCode =
mbedtls_aes_crypt_ctr(c->ctx, src_len, &(c->nc_off), c->counter.v8,
c->stream_block.v8, src, dst);
if (errCode != 0) {
debug_print(srtp_mod_aes_icm, "encrypt error: %d", errCode);
return srtp_err_status_cipher_fail;
}
*dst_len = src_len;
return srtp_err_status_ok;
}

View File

@@ -0,0 +1,415 @@
/*
* aes_icm_nss.c
*
* AES Integer Counter Mode
*
* Richard L. Barnes
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "aes_icm_ext.h"
#include "crypto_types.h"
#include "err.h" /* for srtp_debug */
#include "alloc.h"
#include "cipher_types.h"
#include "cipher_test_cases.h"
srtp_debug_module_t srtp_mod_aes_icm = {
false, /* debugging is off by default */
"aes icm nss" /* printable module name */
};
/*
* integer counter mode works as follows:
*
* 16 bits
* <----->
* +------+------+------+------+------+------+------+------+
* | nonce | packet index | ctr |---+
* +------+------+------+------+------+------+------+------+ |
* |
* +------+------+------+------+------+------+------+------+ v
* | salt |000000|->(+)
* +------+------+------+------+------+------+------+------+ |
* |
* +---------+
* | encrypt |
* +---------+
* |
* +------+------+------+------+------+------+------+------+ |
* | keystream block |<--+
* +------+------+------+------+------+------+------+------+
*
* All fields are big-endian
*
* ctr is the block counter, which increments from zero for
* each packet (16 bits wide)
*
* packet index is distinct for each packet (48 bits wide)
*
* nonce can be distinct across many uses of the same key, or
* can be a fixed value per key, or can be per-packet randomness
* (64 bits)
*
*/
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 30, 38, or 46 for
* AES-128, AES-192, and AES-256 respectively. Note, this key_len
* value is inflated, as it also accounts for the 112 bit salt
* 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_nss_alloc(srtp_cipher_t **c,
size_t key_len,
size_t tlen)
{
srtp_aes_icm_ctx_t *icm;
NSSInitContext *nss;
(void)tlen;
debug_print(srtp_mod_aes_icm, "allocating cipher with key length %zu",
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 &&
key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) {
return srtp_err_status_bad_param;
}
/* Initialize NSS equiv of NSS_NoDB_Init(NULL) */
nss = NSS_InitContext("", "", "", "", NULL,
NSS_INIT_READONLY | NSS_INIT_NOCERTDB |
NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN |
NSS_INIT_OPTIMIZESPACE);
if (!nss) {
return (srtp_err_status_cipher_fail);
}
/* allocate memory a cipher of type aes_icm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
NSS_ShutdownContext(nss);
return srtp_err_status_alloc_fail;
}
icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t));
if (icm == NULL) {
NSS_ShutdownContext(nss);
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
icm->key = NULL;
icm->ctx = NULL;
icm->nss = nss;
/* set pointers */
(*c)->state = icm;
/* setup cipher parameters */
switch (key_len) {
case SRTP_AES_ICM_128_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_128;
(*c)->type = &srtp_aes_icm_128;
icm->key_size = SRTP_AES_128_KEY_LEN;
break;
case SRTP_AES_ICM_192_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_192;
(*c)->type = &srtp_aes_icm_192;
icm->key_size = SRTP_AES_192_KEY_LEN;
break;
case SRTP_AES_ICM_256_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_256;
(*c)->type = &srtp_aes_icm_256;
icm->key_size = SRTP_AES_256_KEY_LEN;
break;
}
/* set key size */
(*c)->key_len = key_len;
return srtp_err_status_ok;
}
/*
* This function deallocates an instance of this engine
*/
static srtp_err_status_t srtp_aes_icm_nss_dealloc(srtp_cipher_t *c)
{
srtp_aes_icm_ctx_t *ctx;
ctx = (srtp_aes_icm_ctx_t *)c->state;
if (ctx) {
/* free any PK11 values that have been created */
if (ctx->key) {
PK11_FreeSymKey(ctx->key);
ctx->key = NULL;
}
if (ctx->ctx) {
PK11_DestroyContext(ctx->ctx, PR_TRUE);
ctx->ctx = NULL;
}
if (ctx->nss) {
NSS_ShutdownContext(ctx->nss);
ctx->nss = NULL;
}
/* zeroize everything */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_icm_ctx_t));
srtp_crypto_free(ctx);
}
/* free memory */
srtp_crypto_free(c);
return (srtp_err_status_ok);
}
/*
* aes_icm_nss_context_init(...) initializes the aes_icm_context
* using the value in key[].
*
* the key is the secret key
*
* 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_nss_context_init(void *cv,
const uint8_t *key)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
/*
* set counter and initial values to 'offset' value, being careful not to
* go past the end of the key buffer
*/
v128_set_to_zero(&c->counter);
v128_set_to_zero(&c->offset);
memcpy(&c->counter, key + c->key_size, SRTP_SALT_LEN);
memcpy(&c->offset, key + c->key_size, SRTP_SALT_LEN);
/* force last two octets of the offset to zero (for srtp compatibility) */
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, "offset: %s", v128_hex_string(&c->offset));
if (c->key) {
PK11_FreeSymKey(c->key);
c->key = NULL;
}
PK11SlotInfo *slot = PK11_GetBestSlot(CKM_AES_CTR, NULL);
if (!slot) {
return srtp_err_status_bad_param;
}
/* explicitly cast away const of key */
SECItem keyItem = { siBuffer, (unsigned char *)(uintptr_t)key,
c->key_size };
c->key = PK11_ImportSymKey(slot, CKM_AES_CTR, PK11_OriginUnwrap,
CKA_ENCRYPT, &keyItem, NULL);
PK11_FreeSlot(slot);
if (!c->key) {
return srtp_err_status_cipher_fail;
}
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_nss_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;
(void)dir;
/* set nonce (for alignment) */
v128_copy_octet_string(&nonce, iv);
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));
/* set up the PK11 context now that we have all the info */
CK_AES_CTR_PARAMS param;
param.ulCounterBits = 16;
memcpy(param.cb, &c->counter, 16);
if (!c->key) {
return srtp_err_status_bad_param;
}
if (c->ctx) {
PK11_DestroyContext(c->ctx, PR_TRUE);
}
SECItem paramItem = { siBuffer, (unsigned char *)&param,
sizeof(CK_AES_CTR_PARAMS) };
c->ctx = PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, c->key,
&paramItem);
if (!c->ctx) {
return srtp_err_status_cipher_fail;
}
return srtp_err_status_ok;
}
/*
* This function encrypts a buffer using AES CTR mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_icm_nss_encrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
if (!c->ctx) {
return srtp_err_status_bad_param;
}
if (dst_len == NULL) {
return srtp_err_status_bad_param;
}
if (*dst_len < src_len) {
return srtp_err_status_buffer_small;
}
int out_len = 0;
int rv = PK11_CipherOp(c->ctx, dst, &out_len, *dst_len, src, src_len);
*dst_len = out_len;
srtp_err_status_t status = srtp_err_status_ok;
if (rv != SECSuccess) {
status = srtp_err_status_cipher_fail;
}
return status;
}
/*
* Name of this crypto engine
*/
static const char srtp_aes_icm_128_nss_description[] =
"AES-128 counter mode using NSS";
static const char srtp_aes_icm_192_nss_description[] =
"AES-192 counter mode using NSS";
static const char srtp_aes_icm_256_nss_description[] =
"AES-256 counter mode using NSS";
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_128 = {
srtp_aes_icm_nss_alloc, /* */
srtp_aes_icm_nss_dealloc, /* */
srtp_aes_icm_nss_context_init, /* */
0, /* set_aad */
srtp_aes_icm_nss_encrypt, /* */
srtp_aes_icm_nss_encrypt, /* */
srtp_aes_icm_nss_set_iv, /* */
srtp_aes_icm_128_nss_description, /* */
&srtp_aes_icm_128_test_case_0, /* */
SRTP_AES_ICM_128 /* */
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_192 = {
srtp_aes_icm_nss_alloc, /* */
srtp_aes_icm_nss_dealloc, /* */
srtp_aes_icm_nss_context_init, /* */
0, /* set_aad */
srtp_aes_icm_nss_encrypt, /* */
srtp_aes_icm_nss_encrypt, /* */
srtp_aes_icm_nss_set_iv, /* */
srtp_aes_icm_192_nss_description, /* */
&srtp_aes_icm_192_test_case_0, /* */
SRTP_AES_ICM_192 /* */
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_256 = {
srtp_aes_icm_nss_alloc, /* */
srtp_aes_icm_nss_dealloc, /* */
srtp_aes_icm_nss_context_init, /* */
0, /* set_aad */
srtp_aes_icm_nss_encrypt, /* */
srtp_aes_icm_nss_encrypt, /* */
srtp_aes_icm_nss_set_iv, /* */
srtp_aes_icm_256_nss_description, /* */
&srtp_aes_icm_256_test_case_0, /* */
SRTP_AES_ICM_256 /* */
};

View File

@@ -0,0 +1,391 @@
/*
* aes_icm_ossl.c
*
* AES Integer Counter Mode
*
* John A. Foley
* Cisco Systems, Inc.
*
* 2/24/2012: This module was modified to use CiscoSSL for AES counter
* mode. Eddy Lem contributed the code to allow this.
*
* 12/20/2012: Added support for AES-192 and AES-256.
*/
/*
*
* Copyright (c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <openssl/evp.h>
#include "aes_icm_ext.h"
#include "crypto_types.h"
#include "err.h" /* for srtp_debug */
#include "alloc.h"
#include "cipher_types.h"
#include "cipher_test_cases.h"
srtp_debug_module_t srtp_mod_aes_icm = {
false, /* debugging is off by default */
"aes icm ossl" /* printable module name */
};
/*
* integer counter mode works as follows:
*
* 16 bits
* <----->
* +------+------+------+------+------+------+------+------+
* | nonce | packet index | ctr |---+
* +------+------+------+------+------+------+------+------+ |
* |
* +------+------+------+------+------+------+------+------+ v
* | salt |000000|->(+)
* +------+------+------+------+------+------+------+------+ |
* |
* +---------+
* | encrypt |
* +---------+
* |
* +------+------+------+------+------+------+------+------+ |
* | keystream block |<--+
* +------+------+------+------+------+------+------+------+
*
* All fields are big-endian
*
* ctr is the block counter, which increments from zero for
* each packet (16 bits wide)
*
* packet index is distinct for each packet (48 bits wide)
*
* nonce can be distinct across many uses of the same key, or
* can be a fixed value per key, or can be per-packet randomness
* (64 bits)
*
*/
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 30, 38, or 46 for
* AES-128, AES-192, and AES-256 respectively. Note, this key_len
* value is inflated, as it also accounts for the 112 bit salt
* 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,
size_t key_len,
size_t tlen)
{
srtp_aes_icm_ctx_t *icm;
(void)tlen;
debug_print(srtp_mod_aes_icm, "allocating cipher with key length %zu",
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 &&
key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) {
return srtp_err_status_bad_param;
}
/* allocate memory a cipher of type aes_icm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
return srtp_err_status_alloc_fail;
}
icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t));
if (icm == NULL) {
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
icm->ctx = EVP_CIPHER_CTX_new();
if (icm->ctx == NULL) {
srtp_crypto_free(icm);
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
/* set pointers */
(*c)->state = icm;
/* setup cipher parameters */
switch (key_len) {
case SRTP_AES_ICM_128_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_128;
(*c)->type = &srtp_aes_icm_128;
icm->key_size = SRTP_AES_128_KEY_LEN;
break;
case SRTP_AES_ICM_192_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_192;
(*c)->type = &srtp_aes_icm_192;
icm->key_size = SRTP_AES_192_KEY_LEN;
break;
case SRTP_AES_ICM_256_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_256;
(*c)->type = &srtp_aes_icm_256;
icm->key_size = SRTP_AES_256_KEY_LEN;
break;
}
/* set key size */
(*c)->key_len = key_len;
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)
{
srtp_aes_icm_ctx_t *ctx;
if (c == NULL) {
return srtp_err_status_bad_param;
}
/*
* Free the EVP context
*/
ctx = (srtp_aes_icm_ctx_t *)c->state;
if (ctx != NULL) {
EVP_CIPHER_CTX_free(ctx->ctx);
/* zeroize the key material */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_icm_ctx_t));
srtp_crypto_free(ctx);
}
/* free memory */
srtp_crypto_free(c);
return srtp_err_status_ok;
}
/*
* aes_icm_openssl_context_init(...) initializes the aes_icm_context
* using the value in key[].
*
* the key is the secret key
*
* 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)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
const EVP_CIPHER *evp;
/*
* set counter and initial values to 'offset' value, being careful not to
* go past the end of the key buffer
*/
v128_set_to_zero(&c->counter);
v128_set_to_zero(&c->offset);
memcpy(&c->counter, key + c->key_size, SRTP_SALT_LEN);
memcpy(&c->offset, key + c->key_size, SRTP_SALT_LEN);
/* force last two octets of the offset to zero (for srtp compatibility) */
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, "offset: %s", v128_hex_string(&c->offset));
switch (c->key_size) {
case SRTP_AES_256_KEY_LEN:
evp = EVP_aes_256_ctr();
break;
case SRTP_AES_192_KEY_LEN:
evp = EVP_aes_192_ctr();
break;
case SRTP_AES_128_KEY_LEN:
evp = EVP_aes_128_ctr();
break;
default:
return srtp_err_status_bad_param;
break;
}
EVP_CIPHER_CTX_reset(c->ctx);
if (!EVP_EncryptInit_ex(c->ctx, evp, NULL, key, NULL)) {
return srtp_err_status_fail;
}
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)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
v128_t nonce;
(void)dir;
/* set nonce (for alignment) */
v128_copy_octet_string(&nonce, iv);
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));
if (!EVP_EncryptInit_ex(c->ctx, NULL, NULL, NULL, c->counter.v8)) {
return srtp_err_status_fail;
}
return srtp_err_status_ok;
}
/*
* This function encrypts a buffer using AES CTR mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_icm_openssl_encrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
int len = 0;
debug_print(srtp_mod_aes_icm, "rs0: %s", v128_hex_string(&c->counter));
if (dst_len == NULL) {
return srtp_err_status_bad_param;
}
if (*dst_len < src_len) {
return srtp_err_status_buffer_small;
}
if (!EVP_EncryptUpdate(c->ctx, dst, &len, src, (int)src_len)) {
return srtp_err_status_cipher_fail;
}
*dst_len = len;
if (!EVP_EncryptFinal_ex(c->ctx, dst + len, &len)) {
return srtp_err_status_cipher_fail;
}
*dst_len += len;
return srtp_err_status_ok;
}
/*
* 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";
/*
* This is the function table for this crypto engine.
* 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, /* */
srtp_aes_icm_128_openssl_description, /* */
&srtp_aes_icm_128_test_case_0, /* */
SRTP_AES_ICM_128 /* */
};
/*
* This is the function table for this crypto engine.
* 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, /* */
srtp_aes_icm_192_openssl_description, /* */
&srtp_aes_icm_192_test_case_0, /* */
SRTP_AES_ICM_192 /* */
};
/*
* This is the function table for this crypto engine.
* 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, /* */
srtp_aes_icm_256_openssl_description, /* */
&srtp_aes_icm_256_test_case_0, /* */
SRTP_AES_ICM_256 /* */
};

View File

@@ -0,0 +1,399 @@
/*
* aes_icm_wssl.c
*
* AES Integer Counter Mode using wolfSSL
*
* Sean Parkinson, wolfSSL
*/
/*
*
* Copyright (c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/aes.h>
#include "aes_icm_ext.h"
#include "crypto_types.h"
#include "err.h" /* for srtp_debug */
#include "alloc.h"
#include "cipher_types.h"
#include "cipher_test_cases.h"
srtp_debug_module_t srtp_mod_aes_icm = {
0, /* debugging is off by default */
"aes icm wssl" /* printable module name */
};
/*
* integer counter mode works as follows:
*
* https://tools.ietf.org/html/rfc3711#section-4.1.1
*
* E(k, IV) || E(k, IV + 1 mod 2^128) || E(k, IV + 2 mod 2^128) ...
* IV = (k_s * 2^16) XOR (SSRC * 2^64) XOR (i * 2^16)
*
* IV SHALL be defined by the SSRC, the SRTP packet index i,
* and the SRTP session salting key k_s.
*
* SSRC: 32bits.
* Sequence number: 16bits.
* nonce is 64bits. .
* packet index = ROC || SEQ. (ROC: Rollover counter)
*
* 16 bits
* <----->
* +------+------+------+------+------+------+------+------+
* | nonce | packet index | ctr |---+
* +------+------+------+------+------+------+------+------+ |
* |
* +------+------+------+------+------+------+------+------+ v
* | salt |000000|->(+)
* +------+------+------+------+------+------+------+------+ |
* |
* +---------+
* | encrypt |
* +---------+
* |
* +------+------+------+------+------+------+------+------+ |
* | keystream block |<--+
* +------+------+------+------+------+------+------+------+
*
* All fields are big-endian
*
* ctr is the block counter, which increments from zero for
* each packet (16 bits wide)
*
* packet index is distinct for each packet (48 bits wide)
*
* nonce can be distinct across many uses of the same key, or
* can be a fixed value per key, or can be per-packet randomness
* (64 bits)
*
*/
/*
* This function allocates a new instance of this crypto engine.
* The key_len parameter should be one of 30, 38, or 46 for
* AES-128, AES-192, and AES-256 respectively. Note, this key_len
* value is inflated, as it also accounts for the 112 bit salt
* 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_wolfssl_alloc(srtp_cipher_t **c,
size_t key_len,
size_t tlen)
{
srtp_aes_icm_ctx_t *icm;
(void)tlen;
debug_print(srtp_mod_aes_icm, "allocating cipher with key length %zu",
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 &&
key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) {
return srtp_err_status_bad_param;
}
/* allocate memory a cipher of type aes_icm */
*c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t));
if (*c == NULL) {
return srtp_err_status_alloc_fail;
}
icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t));
if (icm == NULL) {
srtp_crypto_free(*c);
*c = NULL;
return srtp_err_status_alloc_fail;
}
icm->ctx = NULL;
(*c)->state = icm;
/* setup cipher parameters */
switch (key_len) {
case SRTP_AES_ICM_128_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_128;
(*c)->type = &srtp_aes_icm_128;
icm->key_size = SRTP_AES_128_KEY_LEN;
break;
case SRTP_AES_ICM_192_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_192;
(*c)->type = &srtp_aes_icm_192;
icm->key_size = SRTP_AES_192_KEY_LEN;
break;
case SRTP_AES_ICM_256_KEY_LEN_WSALT:
(*c)->algorithm = SRTP_AES_ICM_256;
(*c)->type = &srtp_aes_icm_256;
icm->key_size = SRTP_AES_256_KEY_LEN;
break;
}
/* set key size */
(*c)->key_len = key_len;
return srtp_err_status_ok;
}
/*
* This function deallocates an instance of this engine
*/
static srtp_err_status_t srtp_aes_icm_wolfssl_dealloc(srtp_cipher_t *c)
{
srtp_aes_icm_ctx_t *ctx;
if (c == NULL) {
return srtp_err_status_bad_param;
}
/*
* Free the aes context
*/
ctx = (srtp_aes_icm_ctx_t *)c->state;
if (ctx != NULL) {
if (ctx->ctx != NULL) {
wc_AesFree(ctx->ctx);
srtp_crypto_free(ctx->ctx);
}
/* zeroize the key material */
octet_string_set_to_zero(ctx, sizeof(srtp_aes_icm_ctx_t));
srtp_crypto_free(ctx);
}
/* free memory */
srtp_crypto_free(c);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_aes_icm_wolfssl_context_init(void *cv,
const uint8_t *key)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
int err;
if (c->ctx == NULL) {
c->ctx = (Aes *)srtp_crypto_alloc(sizeof(Aes));
if (c->ctx == NULL) {
return srtp_err_status_alloc_fail;
}
err = wc_AesInit(c->ctx, NULL, INVALID_DEVID);
if (err < 0) {
debug_print(srtp_mod_aes_icm, "wolfSSL error code: %d", err);
srtp_crypto_free(c->ctx);
c->ctx = NULL;
return srtp_err_status_init_fail;
}
}
/* set pointers */
/*
* set counter and initial values to 'offset' value, being careful not to
* go past the end of the key buffer
*/
v128_set_to_zero(&c->counter);
v128_set_to_zero(&c->offset);
memcpy(&c->counter, key + c->key_size, SRTP_SALT_LEN);
memcpy(&c->offset, key + c->key_size, SRTP_SALT_LEN);
/* force last two octets of the offset to zero (for srtp compatibility) */
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, "offset: %s", v128_hex_string(&c->offset));
switch (c->key_size) {
case SRTP_AES_256_KEY_LEN:
case SRTP_AES_192_KEY_LEN:
case SRTP_AES_128_KEY_LEN:
break;
default:
return srtp_err_status_bad_param;
break;
}
/* Store key. */
if (c->key_size > sizeof(c->key)) {
return srtp_err_status_bad_param;
}
memcpy(c->key, key, c->key_size);
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_wolfssl_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;
int err;
(void)dir;
/* set nonce (for alignment) */
v128_copy_octet_string(&nonce, iv);
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));
/* Counter mode always encrypts. */
err = wc_AesSetKey(c->ctx, c->key, c->key_size, c->counter.v8,
AES_ENCRYPTION);
if (err < 0) {
debug_print(srtp_mod_aes_icm, "wolfSSL error code: %d", err);
return srtp_err_status_fail;
}
return srtp_err_status_ok;
}
/*
* This function encrypts a buffer using AES CTR mode
*
* Parameters:
* c Crypto context
* buf data to encrypt
* enc_len length of encrypt buffer
*/
static srtp_err_status_t srtp_aes_icm_wolfssl_encrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv;
int err;
debug_print(srtp_mod_aes_icm, "rs0: %s", v128_hex_string(&c->counter));
if (dst_len == NULL) {
return srtp_err_status_bad_param;
}
if (*dst_len < src_len) {
return srtp_err_status_buffer_small;
}
err = wc_AesCtrEncrypt(c->ctx, dst, src, src_len);
if (err < 0) {
debug_print(srtp_mod_aes_icm, "wolfSSL encrypt error: %d", err);
return srtp_err_status_cipher_fail;
}
*dst_len = src_len;
return srtp_err_status_ok;
}
/*
* Name of this crypto engine
*/
static const char srtp_aes_icm_128_wolfssl_description[] =
"AES-128 counter mode using wolfSSL";
static const char srtp_aes_icm_192_wolfssl_description[] =
"AES-192 counter mode using wolfSSL";
static const char srtp_aes_icm_256_wolfssl_description[] =
"AES-256 counter mode using wolfSSL";
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_128 = {
srtp_aes_icm_wolfssl_alloc, /* */
srtp_aes_icm_wolfssl_dealloc, /* */
srtp_aes_icm_wolfssl_context_init, /* */
0, /* set_aad */
srtp_aes_icm_wolfssl_encrypt, /* */
srtp_aes_icm_wolfssl_encrypt, /* */
srtp_aes_icm_wolfssl_set_iv, /* */
srtp_aes_icm_128_wolfssl_description, /* */
&srtp_aes_icm_128_test_case_0, /* */
SRTP_AES_ICM_128 /* */
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_192 = {
srtp_aes_icm_wolfssl_alloc, /* */
srtp_aes_icm_wolfssl_dealloc, /* */
srtp_aes_icm_wolfssl_context_init, /* */
0, /* set_aad */
srtp_aes_icm_wolfssl_encrypt, /* */
srtp_aes_icm_wolfssl_encrypt, /* */
srtp_aes_icm_wolfssl_set_iv, /* */
srtp_aes_icm_192_wolfssl_description, /* */
&srtp_aes_icm_192_test_case_0, /* */
SRTP_AES_ICM_192 /* */
};
/*
* This is the function table for this crypto engine.
* note: the encrypt function is identical to the decrypt function
*/
const srtp_cipher_type_t srtp_aes_icm_256 = {
srtp_aes_icm_wolfssl_alloc, /* */
srtp_aes_icm_wolfssl_dealloc, /* */
srtp_aes_icm_wolfssl_context_init, /* */
0, /* set_aad */
srtp_aes_icm_wolfssl_encrypt, /* */
srtp_aes_icm_wolfssl_encrypt, /* */
srtp_aes_icm_wolfssl_set_iv, /* */
srtp_aes_icm_256_wolfssl_description, /* */
&srtp_aes_icm_256_test_case_0, /* */
SRTP_AES_ICM_256 /* */
};

View File

@@ -0,0 +1,651 @@
/*
* cipher.c
*
* cipher meta-functions
*
* David A. McGrew
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "cipher.h"
#include "cipher_priv.h"
#include "crypto_types.h"
#include "err.h" /* for srtp_debug */
#include "alloc.h" /* for crypto_alloc(), crypto_free() */
#include <stdlib.h>
srtp_debug_module_t srtp_mod_cipher = {
false, /* 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,
size_t key_len,
size_t tlen)
{
if (!ct || !ct->alloc) {
return (srtp_err_status_bad_param);
}
return ((ct)->alloc((c), (key_len), (tlen)));
}
srtp_err_status_t srtp_cipher_dealloc(srtp_cipher_t *c)
{
if (!c || !c->type) {
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)
{
if (!c || !c->type || !c->state) {
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,
srtp_cipher_direction_t direction)
{
if (!c || !c->type || !c->state) {
return (srtp_err_status_bad_param);
}
return (((c)->type)->set_iv(((c)->state), iv, direction));
}
srtp_err_status_t srtp_cipher_output(srtp_cipher_t *c,
uint8_t *buffer,
size_t *num_octets_to_output)
{
/* zeroize the buffer */
octet_string_set_to_zero(buffer, *num_octets_to_output);
/* exor keystream into buffer */
return (((c)->type)->encrypt(((c)->state), buffer, *num_octets_to_output,
buffer, num_octets_to_output));
}
srtp_err_status_t srtp_cipher_encrypt(srtp_cipher_t *c,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
if (!c || !c->type || !c->state) {
return (srtp_err_status_bad_param);
}
return (((c)->type)->encrypt(((c)->state), src, src_len, dst, dst_len));
}
srtp_err_status_t srtp_cipher_decrypt(srtp_cipher_t *c,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
if (!c || !c->type || !c->state) {
return (srtp_err_status_bad_param);
}
return (((c)->type)->decrypt(((c)->state), src, src_len, dst, dst_len));
}
srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c,
const uint8_t *aad,
size_t aad_len)
{
if (!c || !c->type || !c->state) {
return (srtp_err_status_bad_param);
}
if (!((c)->type)->set_aad) {
return (srtp_err_status_no_such_op);
}
return (((c)->type)->set_aad(((c)->state), aad, aad_len));
}
/* some bookkeeping functions */
size_t srtp_cipher_get_key_length(const srtp_cipher_t *c)
{
return c->key_len;
}
/*
* A trivial platform independent random source.
* For use in test only.
*/
void srtp_cipher_rand_for_tests(uint8_t *dest, size_t len)
{
/* Generic C-library (rand()) version */
/* This is a random source of last resort */
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... */
*dest++ = val & 0xff;
len--;
}
}
/*
* A trivial platform independent 32 bit random number.
* For use in test only.
*/
uint32_t srtp_cipher_rand_u32_for_tests(void)
{
uint32_t r;
srtp_cipher_rand_for_tests((uint8_t *)&r, sizeof(r));
return r;
}
#define SELF_TEST_BUF_OCTETS 128
#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)
{
const srtp_cipher_test_case_t *test_case = test_data;
srtp_cipher_t *c;
srtp_err_status_t status;
uint8_t buffer[SELF_TEST_BUF_OCTETS];
uint8_t buffer2[SELF_TEST_BUF_OCTETS];
size_t len;
size_t case_num = 0;
debug_print(srtp_mod_cipher, "running self-test for cipher %s",
ct->description);
/*
* check to make sure that we have at least one test case, and
* return an error if we don't - we need to be paranoid here
*/
if (test_case == NULL) {
return srtp_err_status_cant_check;
}
/*
* loop over all test cases, perform known-answer tests of both the
* encryption and decryption functions
*/
while (test_case != NULL) {
/* allocate cipher */
status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets,
test_case->tag_length_octets);
if (status) {
return status;
}
/*
* test the encrypt function
*/
debug_print0(srtp_mod_cipher, "testing encryption");
/* initialize cipher */
status = srtp_cipher_init(c, test_case->key);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
/* copy plaintext into test buffer */
if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
srtp_cipher_dealloc(c);
return srtp_err_status_bad_param;
}
for (size_t 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));
/* set the initialization vector */
status = srtp_cipher_set_iv(c, 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) {
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);
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));
}
/* encrypt */
len = sizeof(buffer);
status = srtp_cipher_encrypt(
c, buffer, test_case->plaintext_length_octets, buffer, &len);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
debug_print(srtp_mod_cipher, "ciphertext: %s",
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) {
srtp_cipher_dealloc(c);
return srtp_err_status_algo_fail;
}
status = srtp_err_status_ok;
for (size_t 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 %zu failed", case_num);
debug_print(srtp_mod_cipher, "(failure at byte %zu)", k);
break;
}
}
if (status) {
debug_print(srtp_mod_cipher, "c computed: %s",
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_cipher_dealloc(c);
return srtp_err_status_algo_fail;
}
/*
* test the decrypt function
*/
debug_print0(srtp_mod_cipher, "testing decryption");
/* re-initialize cipher for decryption */
status = srtp_cipher_init(c, test_case->key);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
/* copy ciphertext into test buffer */
if (test_case->ciphertext_length_octets > SELF_TEST_BUF_OCTETS) {
srtp_cipher_dealloc(c);
return srtp_err_status_bad_param;
}
for (size_t 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));
/* set the initialization vector */
status = srtp_cipher_set_iv(c, 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) {
/*
* Set the AAD
*/
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));
}
/* decrypt */
len = sizeof(buffer);
status = srtp_cipher_decrypt(
c, buffer, test_case->ciphertext_length_octets, buffer, &len);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
debug_print(srtp_mod_cipher, "plaintext: %s",
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) {
srtp_cipher_dealloc(c);
return srtp_err_status_algo_fail;
}
status = srtp_err_status_ok;
for (size_t 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 %zu failed", case_num);
debug_print(srtp_mod_cipher, "(failure at byte %zu)", k);
}
}
if (status) {
debug_print(srtp_mod_cipher, "p computed: %s",
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_cipher_dealloc(c);
return srtp_err_status_algo_fail;
}
/* deallocate the cipher */
status = srtp_cipher_dealloc(c);
if (status) {
return status;
}
/*
* the cipher passed the test case, so move on to the next test
* case in the list; if NULL, we'l proceed to the next test
*/
test_case = test_case->next_test_case;
++case_num;
}
/* now run some random invertibility tests */
/* 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);
if (status) {
return status;
}
for (size_t j = 0; j < NUM_RAND_TESTS; j++) {
size_t plaintext_len;
size_t encrypted_len;
size_t decrypted_len;
uint8_t key[MAX_KEY_LEN];
uint8_t iv[MAX_KEY_LEN];
/* choose a length at random (leaving room for IV and padding) */
plaintext_len =
srtp_cipher_rand_u32_for_tests() % (SELF_TEST_BUF_OCTETS - 64);
debug_print(srtp_mod_cipher, "random plaintext length %zu\n",
plaintext_len);
srtp_cipher_rand_for_tests(buffer, plaintext_len);
debug_print(srtp_mod_cipher, "plaintext: %s",
srtp_octet_string_hex_string(buffer, plaintext_len));
/* copy plaintext into second buffer */
for (size_t i = 0; i < plaintext_len; i++) {
buffer2[i] = buffer[i];
}
/* choose a key at random */
if (test_case->key_length_octets > MAX_KEY_LEN) {
srtp_cipher_dealloc(c);
return srtp_err_status_cant_check;
}
srtp_cipher_rand_for_tests(key, test_case->key_length_octets);
/* chose a random initialization vector */
srtp_cipher_rand_for_tests(iv, MAX_KEY_LEN);
/* initialize cipher */
status = srtp_cipher_init(c, key);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
/* set initialization vector */
status = srtp_cipher_set_iv(c, 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) {
/*
* Set the AAD
*/
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));
}
/* encrypt buffer with cipher */
encrypted_len = sizeof(buffer);
status = srtp_cipher_encrypt(c, buffer, plaintext_len, buffer,
&encrypted_len);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
debug_print(srtp_mod_cipher, "ciphertext: %s",
srtp_octet_string_hex_string(buffer, encrypted_len));
/*
* re-initialize cipher for decryption, re-set the iv, then
* decrypt the ciphertext
*/
status = srtp_cipher_init(c, key);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
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) {
/*
* Set the AAD
*/
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));
}
decrypted_len = sizeof(buffer);
status = srtp_cipher_decrypt(c, buffer, encrypted_len, buffer,
&decrypted_len);
if (status) {
srtp_cipher_dealloc(c);
return status;
}
debug_print(srtp_mod_cipher, "plaintext[2]: %s",
srtp_octet_string_hex_string(buffer, decrypted_len));
/* compare the resulting plaintext with the original one */
if (decrypted_len != plaintext_len) {
srtp_cipher_dealloc(c);
return srtp_err_status_algo_fail;
}
status = srtp_err_status_ok;
for (size_t 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 %zu failed",
case_num);
debug_print(srtp_mod_cipher, "(failure at byte %zu)", k);
}
}
if (status) {
srtp_cipher_dealloc(c);
return srtp_err_status_algo_fail;
}
}
status = srtp_cipher_dealloc(c);
if (status) {
return status;
}
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_err_status_t srtp_cipher_type_self_test(const srtp_cipher_type_t *ct)
{
return srtp_cipher_type_test(ct, ct->test_data);
}
/*
* cipher_bits_per_second(c, l, t) computes (an estimate of) the
* number of bits that a cipher implementation can encrypt in a second
*
* c is a cipher (which MUST be allocated and initialized already), l
* is the length in octets of the test data to be encrypted, and t is
* the number of trials
*
* if an error is encountered, the value 0 is returned
*/
uint64_t srtp_cipher_bits_per_second(srtp_cipher_t *c,
size_t octets_in_buffer,
size_t num_trials)
{
v128_t nonce;
clock_t timer;
uint8_t *enc_buf;
size_t len = octets_in_buffer;
size_t out_len;
size_t tag_len = SRTP_MAX_TAG_LEN;
uint8_t aad[4] = { 0, 0, 0, 0 };
size_t aad_len = 4;
enc_buf = (uint8_t *)srtp_crypto_alloc(octets_in_buffer + tag_len);
if (enc_buf == NULL) {
return 0; /* indicate bad parameters by returning null */
}
/* time repeated trials */
v128_set_to_zero(&nonce);
timer = clock();
for (size_t i = 0; i < num_trials; i++, nonce.v32[3] = (uint32_t)i) {
// Set IV
if (srtp_cipher_set_iv(c, (uint8_t *)&nonce, srtp_direction_encrypt) !=
srtp_err_status_ok) {
srtp_crypto_free(enc_buf);
return 0;
}
// Set (empty) AAD if supported by the cipher
if (c->type->set_aad) {
if (srtp_cipher_set_aad(c, aad, aad_len) != srtp_err_status_ok) {
srtp_crypto_free(enc_buf);
return 0;
}
}
// Encrypt the buffer
out_len = octets_in_buffer + tag_len;
if (srtp_cipher_encrypt(c, enc_buf, len, enc_buf, &out_len) !=
srtp_err_status_ok) {
srtp_crypto_free(enc_buf);
return 0;
}
}
timer = clock() - timer;
srtp_crypto_free(enc_buf);
if (timer == 0) {
/* Too fast! */
return 0;
}
return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer;
}

View File

@@ -0,0 +1,365 @@
/*
*
* Copyright (c) 2013-2021, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "cipher_test_cases.h"
#include <stddef.h>
/*
* 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 */
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 */
};
/*
* 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,
0x97, 0x40, 0xf6, 0x5f, 0x99, 0xb6, 0xbc, 0xf7,
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 */
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 */
};
/*
* 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,
0x2e, 0xc4, 0xcb, 0x0d, 0xc0, 0x25, 0xb5, 0x82,
0x72, 0x14, 0x7c, 0xc4, 0x38, 0x94, 0x4a, 0x98,
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 */
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 */
};
/*
* 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_128_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_128_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_128_test_case_0_plaintext[60] = {
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
0xba, 0x63, 0x7b, 0x39
};
/* clang-format off */
static const uint8_t srtp_aes_gcm_128_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_128_test_case_0_ciphertext[76] = {
0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
0x3d, 0x58, 0xe0, 0x91,
/* the last 16 bytes are the tag */
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_128_test_case_0a = {
SRTP_AES_GCM_128_KEY_LEN_WSALT, /* octets in key */
srtp_aes_gcm_128_test_case_0_key, /* key */
srtp_aes_gcm_128_test_case_0_iv, /* packet index */
60, /* octets in plaintext */
srtp_aes_gcm_128_test_case_0_plaintext, /* plaintext */
68, /* octets in ciphertext */
srtp_aes_gcm_128_test_case_0_ciphertext, /* ciphertext + tag */
20, /* octets in AAD */
srtp_aes_gcm_128_test_case_0_aad, /* AAD */
8, /* */
NULL /* pointer to next testcase */
};
const srtp_cipher_test_case_t srtp_aes_gcm_128_test_case_0 = {
SRTP_AES_GCM_128_KEY_LEN_WSALT, /* octets in key */
srtp_aes_gcm_128_test_case_0_key, /* key */
srtp_aes_gcm_128_test_case_0_iv, /* packet index */
60, /* octets in plaintext */
srtp_aes_gcm_128_test_case_0_plaintext, /* plaintext */
76, /* octets in ciphertext */
srtp_aes_gcm_128_test_case_0_ciphertext, /* ciphertext + tag */
20, /* octets in AAD */
srtp_aes_gcm_128_test_case_0_aad, /* AAD */
16, /* */
&srtp_aes_gcm_128_test_case_0a /* pointer to next testcase */
};
/* clang-format off */
static const uint8_t srtp_aes_gcm_256_test_case_0_key[SRTP_AES_GCM_256_KEY_LEN_WSALT] = {
0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
0xa5, 0x59, 0x09, 0xc5, 0x54, 0x66, 0x93, 0x1c,
0xaf, 0xf5, 0x26, 0x9a, 0x21, 0xd5, 0x14, 0xb2,
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_256_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_256_test_case_0_plaintext[60] = {
0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
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_256_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_256_test_case_0_ciphertext[76] = {
0x0b, 0x11, 0xcf, 0xaf, 0x68, 0x4d, 0xae, 0x46,
0xc7, 0x90, 0xb8, 0x8e, 0xb7, 0x6a, 0x76, 0x2a,
0x94, 0x82, 0xca, 0xab, 0x3e, 0x39, 0xd7, 0x86,
0x1b, 0xc7, 0x93, 0xed, 0x75, 0x7f, 0x23, 0x5a,
0xda, 0xfd, 0xd3, 0xe2, 0x0e, 0x80, 0x87, 0xa9,
0x6d, 0xd7, 0xe2, 0x6a, 0x7d, 0x5f, 0xb4, 0x80,
0xef, 0xef, 0xc5, 0x29, 0x12, 0xd1, 0xaa, 0x10,
0x09, 0xc9, 0x86, 0xc1,
/* the last 16 bytes are the tag */
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_256_test_case_0a = {
SRTP_AES_GCM_256_KEY_LEN_WSALT, /* octets in key */
srtp_aes_gcm_256_test_case_0_key, /* key */
srtp_aes_gcm_256_test_case_0_iv, /* packet index */
60, /* octets in plaintext */
srtp_aes_gcm_256_test_case_0_plaintext, /* plaintext */
68, /* octets in ciphertext */
srtp_aes_gcm_256_test_case_0_ciphertext, /* ciphertext + tag */
20, /* octets in AAD */
srtp_aes_gcm_256_test_case_0_aad, /* AAD */
8, /* */
NULL /* pointer to next testcase */
};
const srtp_cipher_test_case_t srtp_aes_gcm_256_test_case_0 = {
SRTP_AES_GCM_256_KEY_LEN_WSALT, /* octets in key */
srtp_aes_gcm_256_test_case_0_key, /* key */
srtp_aes_gcm_256_test_case_0_iv, /* packet index */
60, /* octets in plaintext */
srtp_aes_gcm_256_test_case_0_plaintext, /* plaintext */
76, /* octets in ciphertext */
srtp_aes_gcm_256_test_case_0_ciphertext, /* ciphertext + tag */
20, /* octets in AAD */
srtp_aes_gcm_256_test_case_0_aad, /* AAD */
16, /* */
&srtp_aes_gcm_256_test_case_0a /* pointer to next testcase */
};

View File

@@ -0,0 +1,53 @@
/*
*
* Copyright (c) 2013-2021, 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 CIPHER_TEST_CASES_H
#define CIPHER_TEST_CASES_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "cipher.h"
extern const srtp_cipher_test_case_t srtp_aes_icm_128_test_case_0;
extern const srtp_cipher_test_case_t srtp_aes_icm_192_test_case_0;
extern const srtp_cipher_test_case_t srtp_aes_icm_256_test_case_0;
extern const srtp_cipher_test_case_t srtp_aes_gcm_128_test_case_0;
extern const srtp_cipher_test_case_t srtp_aes_gcm_256_test_case_0;
#endif

View File

@@ -0,0 +1,166 @@
/*
* null_cipher.c
*
* A null cipher implementation. This cipher leaves the plaintext
* unchanged.
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "datatypes.h"
#include "null_cipher.h"
#include "err.h" /* for srtp_debug */
#include "alloc.h"
#include "cipher_types.h"
static srtp_err_status_t srtp_null_cipher_alloc(srtp_cipher_t **c,
size_t key_len,
size_t tlen)
{
extern const srtp_cipher_type_t srtp_null_cipher;
(void)tlen;
debug_print(srtp_mod_cipher, "allocating cipher with key length %zu",
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;
}
/* set pointers */
(*c)->algorithm = SRTP_NULL_CIPHER;
(*c)->type = &srtp_null_cipher;
(*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)
{
extern const srtp_cipher_type_t srtp_null_cipher;
/* zeroize entire state*/
octet_string_set_to_zero(c, sizeof(srtp_cipher_t));
/* free memory of type null_cipher */
srtp_crypto_free(c);
return srtp_err_status_ok;
}
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; */
(void)cv;
(void)key;
debug_print0(srtp_mod_cipher, "initializing null cipher");
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)
{
/* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */
(void)cv;
(void)iv;
(void)dir;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_null_cipher_encrypt(void *cv,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len)
{
(void)cv;
if (src != dst) {
if (*dst_len < src_len) {
return srtp_err_status_buffer_small;
}
memcpy(dst, src, src_len);
}
*dst_len = src_len;
return srtp_err_status_ok;
}
static const char srtp_null_cipher_description[] = "null cipher";
static const srtp_cipher_test_case_t srtp_null_cipher_test_0 = {
0, /* octets in key */
NULL, /* key */
0, /* packet index */
0, /* octets in plaintext */
NULL, /* plaintext */
0, /* octets in plaintext */
NULL, /* ciphertext */
0, /* */
NULL, /* */
0, /* */
NULL /* pointer to next testcase */
};
/*
* note: the decrypt function is identical 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, /* */
srtp_null_cipher_description, /* */
&srtp_null_cipher_test_0, /* */
SRTP_NULL_CIPHER /* */
};

View File

@@ -0,0 +1,194 @@
/*
* auth.c
*
* some bookkeeping functions for authentication functions
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "auth.h"
#include "err.h" /* for srtp_debug */
#include "datatypes.h" /* for octet_string */
/* the debug module for authentiation */
srtp_debug_module_t srtp_mod_auth = {
false, /* debugging is off by default */
"auth func" /* printable name for module */
};
size_t srtp_auth_get_key_length(const srtp_auth_t *a)
{
return a->key_len;
}
size_t srtp_auth_get_tag_length(const srtp_auth_t *a)
{
return a->out_len;
}
size_t srtp_auth_get_prefix_length(const srtp_auth_t *a)
{
return a->prefix_len;
}
/*
* srtp_auth_type_test() tests an auth function of type ct against
* test cases provided in a list test_data of values of key, data, and tag
* that is known to be good
*/
/* 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)
{
const srtp_auth_test_case_t *test_case = test_data;
srtp_auth_t *a;
srtp_err_status_t status;
uint8_t tag[SELF_TEST_TAG_BUF_OCTETS];
size_t i = 0;
size_t case_num = 0;
debug_print(srtp_mod_auth, "running self-test for auth function %s",
at->description);
/*
* check to make sure that we have at least one test case, and
* return an error if we don't - we need to be paranoid here
*/
if (test_case == NULL) {
return srtp_err_status_cant_check;
}
/* 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;
}
/* allocate auth */
status = srtp_auth_type_alloc(at, &a, test_case->key_length_octets,
test_case->tag_length_octets);
if (status) {
return status;
}
/* initialize auth */
status = srtp_auth_init(a, test_case->key);
if (status) {
srtp_auth_dealloc(a);
return status;
}
status = srtp_auth_start(a);
if (status) {
srtp_auth_dealloc(a);
return status;
}
/* 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);
if (status) {
srtp_auth_dealloc(a);
return status;
}
debug_print(srtp_mod_auth, "key: %s",
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));
debug_print(srtp_mod_auth, "tag expected: %s",
srtp_octet_string_hex_string(test_case->tag,
test_case->tag_length_octets));
/* check the result */
status = srtp_err_status_ok;
for (i = 0; i < test_case->tag_length_octets; i++) {
if (tag[i] != test_case->tag[i]) {
status = srtp_err_status_algo_fail;
debug_print(srtp_mod_auth, "test case %zu failed", case_num);
debug_print(srtp_mod_auth, " (mismatch at octet %zu)", i);
}
}
if (status) {
srtp_auth_dealloc(a);
return srtp_err_status_algo_fail;
}
/* deallocate the auth function */
status = srtp_auth_dealloc(a);
if (status) {
return status;
}
/*
* the auth function passed the test case, so move on to the next test
* case in the list; if NULL, we'll quit and return an OK
*/
test_case = test_case->next_test_case;
++case_num;
}
return srtp_err_status_ok;
}
/*
* 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)
{
return srtp_auth_type_test(at, at->test_data);
}

View File

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

View File

@@ -0,0 +1,48 @@
/*
*
* Copyright (c) 2013-2021, 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 AUTH_TEST_CASES_H
#define AUTH_TEST_CASES_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "auth.h"
extern const srtp_auth_test_case_t srtp_hmac_test_case_0;
#endif

View File

@@ -0,0 +1,248 @@
/*
* hmac.c
*
* implementation of hmac srtp_auth_type_t
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright(c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "hmac.h"
#include "alloc.h"
#include "cipher_types.h"
#include "auth_test_cases.h"
/* the debug module for authentiation */
srtp_debug_module_t srtp_mod_hmac = {
false, /* debugging is off by default */
"hmac sha-1" /* printable name for module */
};
static srtp_err_status_t srtp_hmac_alloc(srtp_auth_t **a,
size_t key_len,
size_t out_len)
{
extern const srtp_auth_type_t srtp_hmac;
uint8_t *pointer;
debug_print(srtp_mod_hmac, "allocating auth func with key length %zu",
key_len);
debug_print(srtp_mod_hmac, " tag length %zu",
out_len);
/*
* check key length - note that we don't support keys larger
* than 20 bytes yet
*/
if (key_len > 20) {
return srtp_err_status_bad_param;
}
/* check output length - should be less than 20 bytes */
if (out_len > 20) {
return srtp_err_status_bad_param;
}
/* 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));
if (pointer == NULL) {
return srtp_err_status_alloc_fail;
}
/* set pointers */
*a = (srtp_auth_t *)pointer;
(*a)->type = &srtp_hmac;
(*a)->state = pointer + sizeof(srtp_auth_t);
(*a)->out_len = out_len;
(*a)->key_len = key_len;
(*a)->prefix_len = 0;
return srtp_err_status_ok;
}
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));
/* free memory */
srtp_crypto_free(a);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_init(void *statev,
const uint8_t *key,
size_t key_len)
{
srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev;
uint8_t ipad[64];
/*
* check key length - note that we don't support keys larger
* than 20 bytes yet
*/
if (key_len > 20) {
return srtp_err_status_bad_param;
}
/*
* set values of ipad and opad by exoring the key into the
* appropriate constant values
*/
for (size_t i = 0; i < key_len; i++) {
ipad[i] = key[i] ^ 0x36;
state->opad[i] = key[i] ^ 0x5c;
}
/* set the rest of ipad, opad to constant values */
for (size_t i = key_len; i < 64; i++) {
ipad[i] = 0x36;
((uint8_t *)state->opad)[i] = 0x5c;
}
debug_print(srtp_mod_hmac, "ipad: %s",
srtp_octet_string_hex_string(ipad, 64));
/* initialize sha1 context */
srtp_sha1_init(&state->init_ctx);
/* hash ipad ^ key */
srtp_sha1_update(&state->init_ctx, ipad, 64);
memcpy(&state->ctx, &state->init_ctx, sizeof(srtp_sha1_ctx_t));
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_start(void *statev)
{
srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev;
memcpy(&state->ctx, &state->init_ctx, sizeof(srtp_sha1_ctx_t));
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_update(void *statev,
const uint8_t *message,
size_t msg_octets)
{
srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev;
debug_print(srtp_mod_hmac, "input: %s",
srtp_octet_string_hex_string(message, msg_octets));
/* hash message into sha1 context */
srtp_sha1_update(&state->ctx, message, msg_octets);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_compute(void *statev,
const uint8_t *message,
size_t msg_octets,
size_t tag_len,
uint8_t *result)
{
srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev;
uint32_t hash_value[5];
uint32_t H[5];
size_t i;
/* check tag length, return error if we can't provide the value expected */
if (tag_len > 20) {
return srtp_err_status_bad_param;
}
/* hash message, copy output into H */
srtp_hmac_update(state, message, msg_octets);
srtp_sha1_final(&state->ctx, H);
/*
* note that we don't need to debug_print() the input, since the
* 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));
/* re-initialize hash context */
srtp_sha1_init(&state->ctx);
/* hash opad ^ key */
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);
/* 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];
}
debug_print(srtp_mod_hmac, "output: %s",
srtp_octet_string_hex_string((uint8_t *)hash_value, tag_len));
return srtp_err_status_ok;
}
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 /* */
};

View File

@@ -0,0 +1,224 @@
/*
* hmac_mbedtls.c
*
* Implementation of hmac srtp_auth_type_t that leverages Mbedtls
*
* YongCheng Yang
*/
/*
*
* Copyright(c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "auth.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#include "auth_test_cases.h"
#include <mbedtls/md.h>
#define SHA1_DIGEST_SIZE 20
/* the debug module for authentiation */
srtp_debug_module_t srtp_mod_hmac = {
false, /* debugging is off by default */
"hmac sha-1 mbedtls" /* printable name for module */
};
static srtp_err_status_t srtp_hmac_mbedtls_alloc(srtp_auth_t **a,
size_t key_len,
size_t out_len)
{
extern const srtp_auth_type_t srtp_hmac;
debug_print(srtp_mod_hmac, "allocating auth func with key length %zu",
key_len);
debug_print(srtp_mod_hmac, " tag length %zu",
out_len);
/* check output length - should be less than 20 bytes */
if (out_len > SHA1_DIGEST_SIZE) {
return srtp_err_status_bad_param;
}
*a = (srtp_auth_t *)srtp_crypto_alloc(sizeof(srtp_auth_t));
if (*a == NULL) {
return srtp_err_status_alloc_fail;
}
// allocate the buffer of mbedtls context.
(*a)->state = srtp_crypto_alloc(sizeof(mbedtls_md_context_t));
if ((*a)->state == NULL) {
srtp_crypto_free(*a);
*a = NULL;
return srtp_err_status_alloc_fail;
}
mbedtls_md_init((mbedtls_md_context_t *)(*a)->state);
/* set pointers */
(*a)->type = &srtp_hmac;
(*a)->out_len = out_len;
(*a)->key_len = key_len;
(*a)->prefix_len = 0;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_mbedtls_dealloc(srtp_auth_t *a)
{
mbedtls_md_context_t *hmac_ctx;
hmac_ctx = (mbedtls_md_context_t *)a->state;
mbedtls_md_free(hmac_ctx);
srtp_crypto_free(hmac_ctx);
/* zeroize entire state*/
octet_string_set_to_zero(a, sizeof(srtp_auth_t));
/* free memory */
srtp_crypto_free(a);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_mbedtls_start(void *statev)
{
mbedtls_md_context_t *state = (mbedtls_md_context_t *)statev;
if (mbedtls_md_hmac_reset(state) != 0) {
return srtp_err_status_auth_fail;
}
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_mbedtls_init(void *statev,
const uint8_t *key,
size_t key_len)
{
mbedtls_md_context_t *state = (mbedtls_md_context_t *)statev;
const mbedtls_md_info_t *info = NULL;
info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
if (info == NULL) {
return srtp_err_status_auth_fail;
}
if (mbedtls_md_setup(state, info, 1) != 0) {
return srtp_err_status_auth_fail;
}
debug_print(srtp_mod_hmac, "mbedtls setup, name: %s",
mbedtls_md_get_name(info));
debug_print(srtp_mod_hmac, "mbedtls setup, size: %d",
mbedtls_md_get_size(info));
if (mbedtls_md_hmac_starts(state, key, key_len) != 0) {
return srtp_err_status_auth_fail;
}
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_mbedtls_update(void *statev,
const uint8_t *message,
size_t msg_octets)
{
mbedtls_md_context_t *state = (mbedtls_md_context_t *)statev;
debug_print(srtp_mod_hmac, "input: %s",
srtp_octet_string_hex_string(message, msg_octets));
if (mbedtls_md_hmac_update(state, message, msg_octets) != 0) {
return srtp_err_status_auth_fail;
}
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_mbedtls_compute(void *statev,
const uint8_t *message,
size_t msg_octets,
size_t tag_len,
uint8_t *result)
{
mbedtls_md_context_t *state = (mbedtls_md_context_t *)statev;
uint8_t hash_value[SHA1_DIGEST_SIZE];
size_t i;
/* check tag length, return error if we can't provide the value expected */
if (tag_len > SHA1_DIGEST_SIZE) {
return srtp_err_status_bad_param;
}
/* hash message, copy output into H */
if (mbedtls_md_hmac_update(statev, message, msg_octets) != 0) {
return srtp_err_status_auth_fail;
}
if (mbedtls_md_hmac_finish(state, hash_value) != 0) {
return srtp_err_status_auth_fail;
}
/* copy hash_value to *result */
for (i = 0; i < tag_len; i++) {
result[i] = hash_value[i];
}
debug_print(srtp_mod_hmac, "output: %s",
srtp_octet_string_hex_string(hash_value, tag_len));
return srtp_err_status_ok;
}
/* end test case 0 */
static const char srtp_hmac_mbedtls_description[] =
"hmac sha-1 authentication function using mbedtls";
/*
* srtp_auth_type_t hmac is the hmac metaobject
*/
const srtp_auth_type_t srtp_hmac = {
srtp_hmac_mbedtls_alloc, /* */
srtp_hmac_mbedtls_dealloc, /* */
srtp_hmac_mbedtls_init, /* */
srtp_hmac_mbedtls_compute, /* */
srtp_hmac_mbedtls_update, /* */
srtp_hmac_mbedtls_start, /* */
srtp_hmac_mbedtls_description, /* */
&srtp_hmac_test_case_0, /* */
SRTP_HMAC_SHA1 /* */
};

View File

@@ -0,0 +1,291 @@
/*
*
* Copyright(c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "auth.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#include "auth_test_cases.h"
#define NSS_PKCS11_2_0_COMPAT 1
#include <nss.h>
#include <pk11pub.h>
#define SHA1_DIGEST_SIZE 20
/* the debug module for authentiation */
srtp_debug_module_t srtp_mod_hmac = {
false, /* debugging is off by default */
"hmac sha-1 nss" /* printable name for module */
};
typedef struct {
NSSInitContext *nss;
PK11SymKey *key;
PK11Context *ctx;
} srtp_hmac_nss_ctx_t;
static srtp_err_status_t srtp_hmac_alloc(srtp_auth_t **a,
size_t key_len,
size_t out_len)
{
extern const srtp_auth_type_t srtp_hmac;
srtp_hmac_nss_ctx_t *hmac;
NSSInitContext *nss;
debug_print(srtp_mod_hmac, "allocating auth func with key length %zu",
key_len);
debug_print(srtp_mod_hmac, " tag length %zu",
out_len);
/* check output length - should be less than 20 bytes */
if (out_len > SHA1_DIGEST_SIZE) {
return srtp_err_status_bad_param;
}
/* Initialize NSS equiv of NSS_NoDB_Init(NULL) */
nss = NSS_InitContext("", "", "", "", NULL,
NSS_INIT_READONLY | NSS_INIT_NOCERTDB |
NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN |
NSS_INIT_OPTIMIZESPACE);
if (!nss) {
return srtp_err_status_auth_fail;
}
*a = (srtp_auth_t *)srtp_crypto_alloc(sizeof(srtp_auth_t));
if (*a == NULL) {
NSS_ShutdownContext(nss);
return srtp_err_status_alloc_fail;
}
hmac =
(srtp_hmac_nss_ctx_t *)srtp_crypto_alloc(sizeof(srtp_hmac_nss_ctx_t));
if (hmac == NULL) {
NSS_ShutdownContext(nss);
srtp_crypto_free(*a);
*a = NULL;
return srtp_err_status_alloc_fail;
}
hmac->nss = nss;
hmac->key = NULL;
hmac->ctx = NULL;
/* set pointers */
(*a)->state = hmac;
(*a)->type = &srtp_hmac;
(*a)->out_len = out_len;
(*a)->key_len = key_len;
(*a)->prefix_len = 0;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_dealloc(srtp_auth_t *a)
{
srtp_hmac_nss_ctx_t *hmac;
hmac = (srtp_hmac_nss_ctx_t *)a->state;
if (hmac) {
/* free any PK11 values that have been created */
if (hmac->key) {
PK11_FreeSymKey(hmac->key);
hmac->key = NULL;
}
if (hmac->ctx) {
PK11_DestroyContext(hmac->ctx, PR_TRUE);
hmac->ctx = NULL;
}
if (hmac->nss) {
NSS_ShutdownContext(hmac->nss);
hmac->nss = NULL;
}
/* zeroize everything */
octet_string_set_to_zero(hmac, sizeof(srtp_hmac_nss_ctx_t));
srtp_crypto_free(hmac);
}
/* free memory */
srtp_crypto_free(a);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_start(void *statev)
{
srtp_hmac_nss_ctx_t *hmac;
hmac = (srtp_hmac_nss_ctx_t *)statev;
if (PK11_DigestBegin(hmac->ctx) != SECSuccess) {
return srtp_err_status_auth_fail;
}
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_init(void *statev,
const uint8_t *key,
size_t key_len)
{
srtp_hmac_nss_ctx_t *hmac;
hmac = (srtp_hmac_nss_ctx_t *)statev;
PK11SymKey *sym_key;
PK11Context *ctx;
if (hmac->ctx) {
PK11_DestroyContext(hmac->ctx, PR_TRUE);
hmac->ctx = NULL;
}
if (hmac->key) {
PK11_FreeSymKey(hmac->key);
hmac->key = NULL;
}
PK11SlotInfo *slot = PK11_GetBestSlot(CKM_SHA_1_HMAC, NULL);
if (!slot) {
return srtp_err_status_bad_param;
}
/* explicitly cast away const of key */
SECItem key_item = { siBuffer, (unsigned char *)(uintptr_t)key, key_len };
sym_key = PK11_ImportSymKey(slot, CKM_SHA_1_HMAC, PK11_OriginUnwrap,
CKA_SIGN, &key_item, NULL);
PK11_FreeSlot(slot);
if (!sym_key) {
return srtp_err_status_auth_fail;
}
SECItem param_item = { siBuffer, NULL, 0 };
ctx = PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, CKA_SIGN, sym_key,
&param_item);
if (!ctx) {
PK11_FreeSymKey(sym_key);
return srtp_err_status_auth_fail;
}
hmac->key = sym_key;
hmac->ctx = ctx;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_update(void *statev,
const uint8_t *message,
size_t msg_octets)
{
srtp_hmac_nss_ctx_t *hmac;
hmac = (srtp_hmac_nss_ctx_t *)statev;
debug_print(srtp_mod_hmac, "input: %s",
srtp_octet_string_hex_string(message, msg_octets));
if (PK11_DigestOp(hmac->ctx, message, msg_octets) != SECSuccess) {
return srtp_err_status_auth_fail;
}
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_compute(void *statev,
const uint8_t *message,
size_t msg_octets,
size_t tag_len,
uint8_t *result)
{
srtp_hmac_nss_ctx_t *hmac;
hmac = (srtp_hmac_nss_ctx_t *)statev;
uint8_t hash_value[SHA1_DIGEST_SIZE];
unsigned int len;
debug_print(srtp_mod_hmac, "input: %s",
srtp_octet_string_hex_string(message, msg_octets));
/* check tag length, return error if we can't provide the value expected */
if (tag_len > SHA1_DIGEST_SIZE) {
return srtp_err_status_bad_param;
}
if (PK11_DigestOp(hmac->ctx, message, msg_octets) != SECSuccess) {
return srtp_err_status_auth_fail;
}
if (PK11_DigestFinal(hmac->ctx, hash_value, &len, SHA1_DIGEST_SIZE) !=
SECSuccess) {
return srtp_err_status_auth_fail;
}
if (len < tag_len) {
return srtp_err_status_auth_fail;
}
/* copy hash_value to *result */
for (size_t i = 0; i < tag_len; i++) {
result[i] = hash_value[i];
}
debug_print(srtp_mod_hmac, "output: %s",
srtp_octet_string_hex_string(hash_value, tag_len));
return srtp_err_status_ok;
}
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 /* */
};

View File

@@ -0,0 +1,343 @@
/*
* hmac_ossl.c
*
* Implementation of hmac srtp_auth_type_t that leverages OpenSSL
*
* John A. Foley
* Cisco Systems, Inc.
*/
/*
*
* Copyright(c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "auth.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#include "auth_test_cases.h"
#include <openssl/evp.h>
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
#define SRTP_OSSL_USE_EVP_MAC
/* before this version reinit of EVP_MAC_CTX was not supported so need to
* duplicate the CTX each time */
#define SRTP_OSSL_MIN_REINIT_VERSION 0x30000030L
#endif
#ifndef SRTP_OSSL_USE_EVP_MAC
#include <openssl/hmac.h>
#endif
#define SHA1_DIGEST_SIZE 20
/* the debug module for authentication */
srtp_debug_module_t srtp_mod_hmac = {
false, /* debugging is off by default */
"hmac sha-1 openssl" /* printable name for module */
};
/*
* There are three different behaviors of OpenSSL HMAC for different versions.
*
* 1. Pre-3.0 - Use HMAC API
* 2. 3.0.0 - 3.0.2 - EVP API is required, but doesn't support reinitialization,
* so we have to use EVP_MAC_CTX_dup
* 3. 3.0.3 and later - EVP API is required and supports reinitialization
*
* The distinction between cases 2 & 3 needs to be made at runtime, because in a
* shared library context you might end up building against 3.0.3 and running
* against 3.0.2.
*/
typedef struct {
#ifdef SRTP_OSSL_USE_EVP_MAC
EVP_MAC *mac;
EVP_MAC_CTX *ctx;
int use_dup;
EVP_MAC_CTX *ctx_dup;
#else
HMAC_CTX *ctx;
#endif
} srtp_hmac_ossl_ctx_t;
static srtp_err_status_t srtp_hmac_alloc(srtp_auth_t **a,
size_t key_len,
size_t out_len)
{
extern const srtp_auth_type_t srtp_hmac;
srtp_hmac_ossl_ctx_t *hmac;
debug_print(srtp_mod_hmac, "allocating auth func with key length %zu",
key_len);
debug_print(srtp_mod_hmac, " tag length %zu",
out_len);
/* check output length - should be less than 20 bytes */
if (out_len > SHA1_DIGEST_SIZE) {
return srtp_err_status_bad_param;
}
*a = (srtp_auth_t *)srtp_crypto_alloc(sizeof(srtp_auth_t));
if (*a == NULL) {
return srtp_err_status_alloc_fail;
}
hmac =
(srtp_hmac_ossl_ctx_t *)srtp_crypto_alloc(sizeof(srtp_hmac_ossl_ctx_t));
if (hmac == NULL) {
srtp_crypto_free(*a);
*a = NULL;
return srtp_err_status_alloc_fail;
}
#ifdef SRTP_OSSL_USE_EVP_MAC
hmac->mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
if (hmac->mac == NULL) {
srtp_crypto_free(hmac);
srtp_crypto_free(*a);
*a = NULL;
return srtp_err_status_alloc_fail;
}
hmac->ctx = EVP_MAC_CTX_new(hmac->mac);
if (hmac->ctx == NULL) {
EVP_MAC_free(hmac->mac);
srtp_crypto_free(hmac);
srtp_crypto_free(*a);
*a = NULL;
return srtp_err_status_alloc_fail;
}
hmac->use_dup =
OpenSSL_version_num() < SRTP_OSSL_MIN_REINIT_VERSION ? 1 : 0;
if (hmac->use_dup) {
debug_print0(srtp_mod_hmac, "using EVP_MAC_CTX_dup");
hmac->ctx_dup = hmac->ctx;
hmac->ctx = NULL;
}
#else
hmac->ctx = HMAC_CTX_new();
if (hmac->ctx == NULL) {
srtp_crypto_free(hmac);
srtp_crypto_free(*a);
*a = NULL;
return srtp_err_status_alloc_fail;
}
#endif
/* set pointers */
(*a)->state = hmac;
(*a)->type = &srtp_hmac;
(*a)->out_len = out_len;
(*a)->key_len = key_len;
(*a)->prefix_len = 0;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_dealloc(srtp_auth_t *a)
{
srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)a->state;
if (hmac) {
#ifdef SRTP_OSSL_USE_EVP_MAC
EVP_MAC_CTX_free(hmac->ctx);
EVP_MAC_CTX_free(hmac->ctx_dup);
EVP_MAC_free(hmac->mac);
#else
HMAC_CTX_free(hmac->ctx);
#endif
/* zeroize entire state*/
octet_string_set_to_zero(hmac, sizeof(srtp_hmac_ossl_ctx_t));
srtp_crypto_free(hmac);
}
/* zeroize entire state*/
octet_string_set_to_zero(a, sizeof(srtp_auth_t));
/* free memory */
srtp_crypto_free(a);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_start(void *statev)
{
srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)statev;
#ifdef SRTP_OSSL_USE_EVP_MAC
if (hmac->use_dup) {
EVP_MAC_CTX_free(hmac->ctx);
hmac->ctx = EVP_MAC_CTX_dup(hmac->ctx_dup);
if (hmac->ctx == NULL) {
return srtp_err_status_alloc_fail;
}
} else {
if (EVP_MAC_init(hmac->ctx, NULL, 0, NULL) == 0) {
return srtp_err_status_auth_fail;
}
}
#else
if (HMAC_Init_ex(hmac->ctx, NULL, 0, NULL, NULL) == 0) {
return srtp_err_status_auth_fail;
}
#endif
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_init(void *statev,
const uint8_t *key,
size_t key_len)
{
srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)statev;
#ifdef SRTP_OSSL_USE_EVP_MAC
OSSL_PARAM params[2];
params[0] = OSSL_PARAM_construct_utf8_string("digest", "SHA1", 0);
params[1] = OSSL_PARAM_construct_end();
if (EVP_MAC_init(hmac->use_dup ? hmac->ctx_dup : hmac->ctx, key, key_len,
params) == 0) {
return srtp_err_status_auth_fail;
}
#else
if (HMAC_Init_ex(hmac->ctx, key, key_len, EVP_sha1(), NULL) == 0) {
return srtp_err_status_auth_fail;
}
#endif
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_update(void *statev,
const uint8_t *message,
size_t msg_octets)
{
srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)statev;
debug_print(srtp_mod_hmac, "input: %s",
srtp_octet_string_hex_string(message, msg_octets));
#ifdef SRTP_OSSL_USE_EVP_MAC
if (EVP_MAC_update(hmac->ctx, message, msg_octets) == 0) {
return srtp_err_status_auth_fail;
}
#else
if (HMAC_Update(hmac->ctx, message, msg_octets) == 0) {
return srtp_err_status_auth_fail;
}
#endif
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_compute(void *statev,
const uint8_t *message,
size_t msg_octets,
size_t tag_len,
uint8_t *result)
{
srtp_hmac_ossl_ctx_t *hmac = (srtp_hmac_ossl_ctx_t *)statev;
uint8_t hash_value[SHA1_DIGEST_SIZE];
#ifdef SRTP_OSSL_USE_EVP_MAC
size_t len;
#else
unsigned int len;
#endif
debug_print(srtp_mod_hmac, "input: %s",
srtp_octet_string_hex_string(message, msg_octets));
/* check tag length, return error if we can't provide the value expected */
if (tag_len > SHA1_DIGEST_SIZE) {
return srtp_err_status_bad_param;
}
/* hash message, copy output into H */
#ifdef SRTP_OSSL_USE_EVP_MAC
if (EVP_MAC_update(hmac->ctx, message, msg_octets) == 0) {
return srtp_err_status_auth_fail;
}
if (EVP_MAC_final(hmac->ctx, hash_value, &len, sizeof hash_value) == 0) {
return srtp_err_status_auth_fail;
}
#else
if (HMAC_Update(hmac->ctx, message, msg_octets) == 0) {
return srtp_err_status_auth_fail;
}
if (HMAC_Final(hmac->ctx, hash_value, &len) == 0) {
return srtp_err_status_auth_fail;
}
#endif
if (len < tag_len) {
return srtp_err_status_auth_fail;
}
/* copy hash_value to *result */
for (size_t i = 0; i < tag_len; i++) {
result[i] = hash_value[i];
}
debug_print(srtp_mod_hmac, "output: %s",
srtp_octet_string_hex_string(hash_value, tag_len));
return srtp_err_status_ok;
}
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 /* */
};

View File

@@ -0,0 +1,228 @@
/*
* hmac_wssl.c
*
* Implementation of hmac srtp_auth_type_t that uses wolfSSL
*
* Sean Parkinson, wolfSSL
*/
/*
*
* Copyright(c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/hmac.h>
#include "auth.h"
#include "alloc.h"
#include "err.h" /* for srtp_debug */
#include "auth_test_cases.h"
#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 wssl" /* printable name for module */
};
static srtp_err_status_t srtp_hmac_wolfssl_alloc(srtp_auth_t **a,
size_t key_len,
size_t out_len)
{
extern const srtp_auth_type_t srtp_hmac;
int err;
debug_print(srtp_mod_hmac, "allocating auth func with key length %zu",
key_len);
debug_print(srtp_mod_hmac, " tag length %zu",
out_len);
/* check output length - should be less than 20 bytes */
if (out_len > SHA1_DIGEST_SIZE) {
return srtp_err_status_bad_param;
}
*a = (srtp_auth_t *)srtp_crypto_alloc(sizeof(srtp_auth_t));
if (*a == NULL) {
return srtp_err_status_alloc_fail;
}
// allocate the buffer of wolfssl context.
(*a)->state = srtp_crypto_alloc(sizeof(Hmac));
if ((*a)->state == NULL) {
srtp_crypto_free(*a);
*a = NULL;
return srtp_err_status_alloc_fail;
}
err = wc_HmacInit((Hmac *)(*a)->state, NULL, INVALID_DEVID);
if (err < 0) {
srtp_crypto_free((*a)->state);
srtp_crypto_free(*a);
*a = NULL;
debug_print(srtp_mod_hmac, "wolfSSL error code: %d", err);
return srtp_err_status_init_fail;
}
/* set pointers */
(*a)->type = &srtp_hmac;
(*a)->out_len = out_len;
(*a)->key_len = key_len;
(*a)->prefix_len = 0;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_wolfssl_dealloc(srtp_auth_t *a)
{
wc_HmacFree((Hmac *)a->state);
srtp_crypto_free(a->state);
/* zeroize entire state*/
octet_string_set_to_zero(a, sizeof(srtp_auth_t));
/* free memory */
srtp_crypto_free(a);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_wolfssl_start(void *statev)
{
(void)statev;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_wolfssl_init(void *statev,
const uint8_t *key,
size_t key_len)
{
Hmac *state = (Hmac *)statev;
int err;
err = wc_HmacSetKey(state, WC_SHA, key, key_len);
if (err < 0) {
debug_print(srtp_mod_hmac, "wolfSSL error code: %d", err);
return srtp_err_status_auth_fail;
}
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_wolfssl_update(void *statev,
const uint8_t *message,
size_t msg_octets)
{
Hmac *state = (Hmac *)statev;
int err;
debug_print(srtp_mod_hmac, "input: %s",
srtp_octet_string_hex_string(message, msg_octets));
err = wc_HmacUpdate(state, message, msg_octets);
if (err < 0) {
debug_print(srtp_mod_hmac, "wolfSSL error code: %d", err);
return srtp_err_status_auth_fail;
}
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_hmac_wolfssl_compute(void *statev,
const uint8_t *message,
size_t msg_octets,
size_t tag_len,
uint8_t *result)
{
Hmac *state = (Hmac *)statev;
uint8_t hash_value[WC_SHA_DIGEST_SIZE];
int err;
int i;
debug_print(srtp_mod_hmac, "input: %s",
srtp_octet_string_hex_string(message, msg_octets));
/* check tag length, return error if we can't provide the value expected */
if (tag_len > WC_SHA_DIGEST_SIZE) {
return srtp_err_status_bad_param;
}
/* hash message, copy output into H */
err = wc_HmacUpdate(state, message, msg_octets);
if (err < 0) {
debug_print(srtp_mod_hmac, "wolfSSL error code: %d", err);
return srtp_err_status_auth_fail;
}
err = wc_HmacFinal(state, hash_value);
if (err < 0) {
debug_print(srtp_mod_hmac, "wolfSSL error code: %d", err);
return srtp_err_status_auth_fail;
}
/* copy hash_value to *result */
for (i = 0; i < (int)tag_len; i++) {
result[i] = hash_value[i];
}
debug_print(srtp_mod_hmac, "output: %s",
srtp_octet_string_hex_string(hash_value, tag_len));
return srtp_err_status_ok;
}
/* end test case 0 */
static const char srtp_hmac_wolfssl_description[] =
"hmac sha-1 authentication function using wolfSSL";
/*
* srtp_auth_type_t hmac is the hmac metaobject
*/
const srtp_auth_type_t srtp_hmac = {
srtp_hmac_wolfssl_alloc, /* */
srtp_hmac_wolfssl_dealloc, /* */
srtp_hmac_wolfssl_init, /* */
srtp_hmac_wolfssl_compute, /* */
srtp_hmac_wolfssl_update, /* */
srtp_hmac_wolfssl_start, /* */
srtp_hmac_wolfssl_description, /* */
&srtp_hmac_test_case_0, /* */
SRTP_HMAC_SHA1 /* */
};

View File

@@ -0,0 +1,181 @@
/*
* null_auth.c
*
* implements the do-nothing auth algorithm
*
* David A. McGrew
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "null_auth.h"
#include "err.h" /* for srtp_debug */
#include "alloc.h"
#include "cipher_types.h"
static srtp_err_status_t srtp_null_auth_alloc(srtp_auth_t **a,
size_t key_len,
size_t 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 %zu",
key_len);
debug_print(srtp_mod_auth, " tag length %zu",
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));
if (pointer == NULL) {
return srtp_err_status_alloc_fail;
}
/* set pointers */
*a = (srtp_auth_t *)pointer;
(*a)->type = &srtp_null_auth;
(*a)->state = pointer + sizeof(srtp_auth_t);
(*a)->out_len = out_len;
(*a)->prefix_len = out_len;
(*a)->key_len = key_len;
return srtp_err_status_ok;
}
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));
/* free memory */
srtp_crypto_free(a);
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_null_auth_init(void *statev,
const uint8_t *key,
size_t key_len)
{
/* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */
(void)statev;
(void)key;
(void)key_len;
/* accept any length of key, and do nothing */
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_null_auth_compute(void *statev,
const uint8_t *message,
size_t msg_octets,
size_t tag_len,
uint8_t *result)
{
/* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */
(void)statev;
(void)message;
(void)msg_octets;
(void)tag_len;
(void)result;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_null_auth_update(void *statev,
const uint8_t *message,
size_t msg_octets)
{
/* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */
(void)statev;
(void)message;
(void)msg_octets;
return srtp_err_status_ok;
}
static srtp_err_status_t srtp_null_auth_start(void *statev)
{
/* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */
(void)statev;
return srtp_err_status_ok;
}
/*
* srtp_auth_type_t - defines description, test case, and null_auth
* metaobject
*/
/* 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 */
};
/* 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 /* */
};

View File

@@ -0,0 +1,463 @@
/*
* sha1.c
*
* an implementation of the Secure Hash Algorithm v.1 (SHA-1),
* specified in FIPS 180-1
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "sha1.h"
srtp_debug_module_t srtp_mod_sha1 = {
false, /* 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 S30(X) ((X << 30) | (X >> 2))
#define f0(B, C, D) ((B & C) | (~B & D))
#define f1(B, C, D) (B ^ C ^ D)
#define f2(B, C, D) ((B & C) | (B & D) | (C & D))
#define f3(B, C, D) (B ^ C ^ D)
/*
* nota bene: the variable K0 appears in the curses library, so we
* give longer names to these variables to avoid spurious warnings
* 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 */
/*
* srtp_sha1_core(M, H) computes the core compression function, where M is
* the next part of the message (in network byte order) and H is the
* intermediate state { H0, H1, ...} (in host byte order)
*
* this function does not do any of the padding required in the
* complete SHA1 function
*
* this function is used in the SEAL 3.0 key setup routines
* (crypto/cipher/seal.c)
*/
void srtp_sha1_core(const uint32_t M[16], uint32_t hash_value[5])
{
uint32_t H0;
uint32_t H1;
uint32_t H2;
uint32_t H3;
uint32_t H4;
uint32_t W[80];
uint32_t A, B, C, D, E, TEMP;
size_t t;
/* copy hash_value into H0, H1, H2, H3, H4 */
H0 = hash_value[0];
H1 = hash_value[1];
H2 = hash_value[2];
H3 = hash_value[3];
H4 = hash_value[4];
/* 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[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);
/* process the remainder of the array */
for (t = 32; t < 80; t++) {
TEMP = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
W[t] = S1(TEMP);
}
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;
}
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;
}
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;
}
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;
}
hash_value[0] = H0 + A;
hash_value[1] = H1 + B;
hash_value[2] = H2 + C;
hash_value[3] = H3 + D;
hash_value[4] = H4 + E;
return;
}
void srtp_sha1_init(srtp_sha1_ctx_t *ctx)
{
/* initialize state vector */
ctx->H[0] = 0x67452301;
ctx->H[1] = 0xefcdab89;
ctx->H[2] = 0x98badcfe;
ctx->H[3] = 0x10325476;
ctx->H[4] = 0xc3d2e1f0;
/* indicate that message buffer is empty */
ctx->octets_in_buffer = 0;
/* 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,
size_t octets_in_msg)
{
size_t i;
uint8_t *buf = (uint8_t *)ctx->M;
/* update message bit-count */
ctx->num_bits_in_msg += (uint32_t)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
*/
octets_in_msg -= (64 - ctx->octets_in_buffer);
for (i = ctx->octets_in_buffer; i < 64; i++) {
buf[i] = *msg++;
}
ctx->octets_in_buffer = 0;
/* process a whole block */
debug_print0(srtp_mod_sha1, "(update) running srtp_sha1_core()");
srtp_sha1_core(ctx->M, ctx->H);
} else {
debug_print0(srtp_mod_sha1,
"(update) not running srtp_sha1_core()");
for (i = ctx->octets_in_buffer;
i < (ctx->octets_in_buffer + octets_in_msg); i++) {
buf[i] = *msg++;
}
ctx->octets_in_buffer += octets_in_msg;
octets_in_msg = 0;
}
}
}
/*
* srtp_sha1_final(ctx, output) computes the result for ctx and copies it
* into the twenty octets located at *output
*/
void srtp_sha1_final(srtp_sha1_ctx_t *ctx, uint32_t output[5])
{
uint32_t A, B, C, D, E, TEMP;
uint32_t W[80];
size_t i, t;
/*
* process the remaining octets_in_buffer, padding and terminating as
* necessary
*/
{
size_t tail = ctx->octets_in_buffer % 4;
/* copy/xor message into array */
for (i = 0; i < (ctx->octets_in_buffer + 3) / 4; i++) {
W[i] = be32_to_cpu(ctx->M[i]);
}
/* set the high bit of the octet immediately following the message */
switch (tail) {
case (3):
W[i - 1] = (be32_to_cpu(ctx->M[i - 1]) & 0xffffff00) | 0x80;
W[i] = 0x0;
break;
case (2):
W[i - 1] = (be32_to_cpu(ctx->M[i - 1]) & 0xffff0000) | 0x8000;
W[i] = 0x0;
break;
case (1):
W[i - 1] = (be32_to_cpu(ctx->M[i - 1]) & 0xff000000) | 0x800000;
W[i] = 0x0;
break;
case (0):
W[i] = 0x80000000;
break;
}
/* zeroize remaining words */
for (i++; i < 15; i++) {
W[i] = 0x0;
}
/*
* if there is room at the end of the word array, then set the
* last word to the bit-length of the message; otherwise, set that
* word to zero and then we need to do one more run of the
* compression algo.
*/
if (ctx->octets_in_buffer < 56) {
W[15] = ctx->num_bits_in_msg;
} else if (ctx->octets_in_buffer < 60) {
W[15] = 0x0;
}
/* process the word array */
for (t = 16; t < 80; t++) {
TEMP = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
W[t] = S1(TEMP);
}
A = ctx->H[0];
B = ctx->H[1];
C = ctx->H[2];
D = ctx->H[3];
E = ctx->H[4];
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;
}
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;
}
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;
}
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;
}
ctx->H[0] += A;
ctx->H[1] += B;
ctx->H[2] += C;
ctx->H[3] += D;
ctx->H[4] += E;
}
debug_print0(srtp_mod_sha1, "(final) running srtp_sha1_core()");
if (ctx->octets_in_buffer >= 56) {
debug_print0(srtp_mod_sha1, "(final) running srtp_sha1_core() again");
/* we need to do one final run of the compression algo */
/*
* set initial part of word array to zeros, and set the
* final part to the number of bits in the message
*/
for (i = 0; i < 15; i++) {
W[i] = 0x0;
}
W[15] = ctx->num_bits_in_msg;
/* process the word array */
for (t = 16; t < 80; t++) {
TEMP = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
W[t] = S1(TEMP);
}
A = ctx->H[0];
B = ctx->H[1];
C = ctx->H[2];
D = ctx->H[3];
E = ctx->H[4];
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;
}
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;
}
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;
}
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;
}
ctx->H[0] += A;
ctx->H[1] += B;
ctx->H[2] += C;
ctx->H[3] += D;
ctx->H[4] += E;
}
/* copy result into output buffer */
output[0] = be32_to_cpu(ctx->H[0]);
output[1] = be32_to_cpu(ctx->H[1]);
output[2] = be32_to_cpu(ctx->H[2]);
output[3] = be32_to_cpu(ctx->H[3]);
output[4] = be32_to_cpu(ctx->H[4]);
/* indicate that message buffer in context is empty */
ctx->octets_in_buffer = 0;
return;
}

View File

@@ -0,0 +1,83 @@
/*
* aes.h
*
* header file for the AES block cipher
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef AES_H
#define AES_H
#include "datatypes.h"
#include "err.h"
#ifdef __cplusplus
extern "C" {
#endif
/* aes internals */
typedef struct {
v128_t round[15];
size_t num_rounds;
} srtp_aes_expanded_key_t;
srtp_err_status_t srtp_aes_expand_encryption_key(
const uint8_t *key,
size_t key_len,
srtp_aes_expanded_key_t *expanded_key);
srtp_err_status_t srtp_aes_expand_decryption_key(
const uint8_t *key,
size_t 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_decrypt(v128_t *plaintext,
const srtp_aes_expanded_key_t *exp_key);
#ifdef __cplusplus
}
#endif
#endif /* AES_H */

View File

@@ -0,0 +1,134 @@
/*
* aes_gcm.h
*
* Header for AES Galois Counter Mode.
*
* John A. Foley
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2013-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef AES_GCM_H
#define AES_GCM_H
#include "cipher.h"
#include "srtp.h"
#include "datatypes.h"
#ifdef OPENSSL
#include <openssl/evp.h>
#include <openssl/aes.h>
typedef struct {
size_t key_size;
size_t tag_len;
EVP_CIPHER_CTX *ctx;
srtp_cipher_direction_t dir;
} srtp_aes_gcm_ctx_t;
#endif /* OPENSSL */
#ifdef WOLFSSL
#define MAX_AD_SIZE 2048
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/aes.h>
typedef struct {
size_t key_size;
size_t tag_len;
#ifndef WOLFSSL_AESGCM_STREAM
size_t aad_size;
size_t iv_len;
uint8_t iv[GCM_NONCE_MID_SZ];
uint8_t aad[MAX_AD_SIZE];
#endif
Aes *ctx;
srtp_cipher_direction_t dir;
} srtp_aes_gcm_ctx_t;
#endif /* WOLFSSL */
#ifdef MBEDTLS
#define MAX_AD_SIZE 2048
#include <mbedtls/aes.h>
#include <mbedtls/gcm.h>
typedef struct {
size_t key_size;
size_t tag_len;
size_t aad_size;
size_t iv_len;
uint8_t iv[12];
uint8_t aad[MAX_AD_SIZE];
mbedtls_gcm_context *ctx;
srtp_cipher_direction_t dir;
} srtp_aes_gcm_ctx_t;
#endif /* MBEDTLS */
#ifdef NSS
#define NSS_PKCS11_2_0_COMPAT 1
#include <nss.h>
#include <pk11pub.h>
#define MAX_AD_SIZE 2048
typedef struct {
size_t key_size;
size_t tag_size;
srtp_cipher_direction_t dir;
NSSInitContext *nss;
PK11SymKey *key;
uint8_t iv[12];
uint8_t aad[MAX_AD_SIZE];
size_t aad_size;
CK_GCM_PARAMS params;
} srtp_aes_gcm_ctx_t;
#endif /* NSS */
#endif /* AES_GCM_H */

View File

@@ -0,0 +1,62 @@
/*
* aes_icm.h
*
* Header for AES Integer Counter Mode.
*
* David A. McGrew
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef AES_ICM_H
#define AES_ICM_H
#include "aes.h"
#include "cipher.h"
typedef struct {
v128_t counter; /* holds the counter value */
v128_t offset; /* initial offset value */
v128_t keystream_buffer; /* buffers bytes of keystream */
srtp_aes_expanded_key_t expanded_key; /* the cipher key */
size_t bytes_in_buffer; /* number of unused bytes in buffer */
size_t key_size; /* AES key size + 14 byte SALT */
} srtp_aes_icm_ctx_t;
#endif /* AES_ICM_H */

View File

@@ -0,0 +1,112 @@
/*
* aes_icm.h
*
* Header for AES Integer Counter Mode.
*
* David A. McGrew
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef AES_ICM_H
#define AES_ICM_H
#include "cipher.h"
#include "datatypes.h"
#ifdef OPENSSL
#include <openssl/evp.h>
#include <openssl/aes.h>
typedef struct {
v128_t counter; /* holds the counter value */
v128_t offset; /* initial offset value */
size_t key_size;
EVP_CIPHER_CTX *ctx;
} srtp_aes_icm_ctx_t;
#endif /* OPENSSL */
#ifdef WOLFSSL
#include <wolfssl/wolfcrypt/aes.h>
typedef struct {
v128_t counter; /* holds the counter value */
v128_t offset; /* initial offset value */
uint8_t key[SRTP_AES_256_KEY_LEN];
size_t key_size;
Aes *ctx;
} srtp_aes_icm_ctx_t;
#endif /* WOLFSSL */
#ifdef MBEDTLS
#include <mbedtls/aes.h>
typedef struct {
v128_t counter; /* holds the counter value */
v128_t offset; /* initial offset value */
v128_t stream_block;
size_t nc_off;
size_t key_size;
mbedtls_aes_context *ctx;
} srtp_aes_icm_ctx_t;
#endif /* MBEDTLS */
#ifdef NSS
#define NSS_PKCS11_2_0_COMPAT 1
#include <nss.h>
#include <pk11pub.h>
typedef struct {
v128_t counter;
v128_t offset;
size_t key_size;
uint8_t iv[16];
NSSInitContext *nss;
PK11SymKey *key;
PK11Context *ctx;
} srtp_aes_icm_ctx_t;
#endif /* NSS */
#endif /* AES_ICM_H */

View File

@@ -0,0 +1,76 @@
/*
* alloc.h
*
* 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
* 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 CRYPTO_ALLOC_H
#define CRYPTO_ALLOC_H
#include "datatypes.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* 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
}
#endif
#endif /* CRYPTO_ALLOC_H */

View File

@@ -0,0 +1,173 @@
/*
* auth.h
*
* common interface to authentication functions
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef SRTP_AUTH_H
#define SRTP_AUTH_H
#include "srtp.h"
#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 srtp_err_status_t (*srtp_auth_alloc_func)(srtp_auth_pointer_t *ap,
size_t key_len,
size_t out_len);
typedef srtp_err_status_t (*srtp_auth_init_func)(void *state,
const uint8_t *key,
size_t 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,
size_t octets_to_auth,
size_t tag_len,
uint8_t *tag);
typedef srtp_err_status_t (*srtp_auth_update_func)(void *state,
const uint8_t *buffer,
size_t 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) \
((at)->alloc((a), (klen), (outlen)))
#define srtp_auth_init(a, key) \
(((a)->type)->init((a)->state, (key), ((a)->key_len)))
#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) \
(((a)->type)->update((a)->state, (buf), (len)))
#define srtp_auth_start(a) (((a)->type)->start((a)->state))
#define srtp_auth_dealloc(c) (((c)->type)->dealloc(c))
/* functions to get information about a particular auth_t */
size_t srtp_auth_get_key_length(const struct srtp_auth_t *a);
size_t srtp_auth_get_tag_length(const struct srtp_auth_t *a);
size_t srtp_auth_get_prefix_length(const struct srtp_auth_t *a);
/*
* srtp_auth_test_case_t is a (list of) key/message/tag values that are
* known to be correct for a particular cipher. this data can be used
* to test an implementation in an on-the-fly self test of the
* correctness of the implementation. (see the srtp_auth_type_self_test()
* function below)
*/
typedef struct srtp_auth_test_case_t {
size_t key_length_octets; /* octets in key */
const uint8_t *key; /* key */
size_t data_length_octets; /* octets in data */
const uint8_t *data; /* data */
size_t 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 */
typedef struct srtp_auth_type_t {
srtp_auth_alloc_func alloc;
srtp_auth_dealloc_func dealloc;
srtp_auth_init_func init;
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;
srtp_auth_type_id_t id;
} srtp_auth_type_t;
typedef struct srtp_auth_t {
const srtp_auth_type_t *type;
void *state;
size_t out_len; /* length of output tag in octets */
size_t key_len; /* length of key in octets */
size_t prefix_len; /* length of keystream prefix */
} srtp_auth_t;
/*
* srtp_auth_type_self_test() tests an auth_type against test cases
* provided in an array of values of key/message/tag that is known to
* be good
*/
srtp_err_status_t srtp_auth_type_self_test(const srtp_auth_type_t *at);
/*
* srtp_auth_type_test() tests an auth_type against external test cases
* 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_replace_auth_type(ct, id)
*
* replaces srtp's kernel's auth type implementation for the auth_type id
* 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);
#ifdef __cplusplus
}
#endif
#endif /* SRTP_AUTH_H */

View File

@@ -0,0 +1,242 @@
/*
* cipher.h
*
* common interface to ciphers
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef SRTP_CIPHER_H
#define SRTP_CIPHER_H
#include "srtp.h"
#include "crypto_types.h" /* for values of cipher_type_id_t */
#ifdef __cplusplus
extern "C" {
#endif
/*
* srtp_cipher_direction_t defines a particular cipher operation.
*
* A srtp_cipher_direction_t is an enum that describes a particular cipher
* operation, i.e. encryption or decryption. For some ciphers, this
* distinction does not matter, but for others, it is essential.
*/
typedef enum {
srtp_direction_encrypt, /**< encryption (convert plaintext to ciphertext) */
srtp_direction_decrypt, /**< decryption (convert ciphertext to plaintext) */
srtp_direction_any /**< encryption or decryption */
} srtp_cipher_direction_t;
/*
* 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;
/*
* 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,
size_t key_len,
size_t 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);
/* 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);
/*
* 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,
size_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,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len);
/* a srtp_cipher_decrypt_func_t decrypts data in-place */
typedef srtp_err_status_t (*srtp_cipher_decrypt_func_t)(void *state,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len);
/*
* 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);
/*
* srtp_cipher_test_case_t is a (list of) key, salt, plaintext, ciphertext,
* and aad values that are known to be correct for a
* particular cipher. this data can be used to test an implementation
* in an on-the-fly self test of the correctness of the implementation.
* (see the srtp_cipher_type_self_test() function below)
*/
typedef struct srtp_cipher_test_case_t {
size_t key_length_octets; /* octets in key */
const uint8_t *key; /* key */
uint8_t *idx; /* packet index */
size_t plaintext_length_octets; /* octets in plaintext */
const uint8_t *plaintext; /* plaintext */
size_t ciphertext_length_octets; /* octets in plaintext */
const uint8_t *ciphertext; /* ciphertext */
size_t aad_length_octets; /* octets in AAD */
const uint8_t *aad; /* AAD */
size_t 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 */
typedef struct srtp_cipher_type_t {
srtp_cipher_alloc_func_t alloc;
srtp_cipher_dealloc_func_t dealloc;
srtp_cipher_init_func_t init;
srtp_cipher_set_aad_func_t set_aad;
srtp_cipher_encrypt_func_t encrypt;
srtp_cipher_decrypt_func_t decrypt;
srtp_cipher_set_iv_func_t set_iv;
const char *description;
const srtp_cipher_test_case_t *test_data;
srtp_cipher_type_id_t id;
} srtp_cipher_type_t;
/*
* srtp_cipher_t defines an instantiation of a particular cipher, with fixed
* key length, key and salt values
*/
typedef struct srtp_cipher_t {
const srtp_cipher_type_t *type;
void *state;
size_t key_len;
srtp_cipher_type_id_t algorithm;
} srtp_cipher_t;
/* some bookkeeping functions */
size_t 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
* that is known to be good
*/
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
* 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_cipher_bits_per_second(c, l, t) computes (an estimate of) the
* number of bits that a cipher implementation can encrypt in a second
*
* c is a cipher (which MUST be allocated and initialized already), l
* is the length in octets of the test data to be encrypted, and t is
* the number of trials
*
* if an error is encountered, then the value 0 is returned
*/
uint64_t srtp_cipher_bits_per_second(srtp_cipher_t *c,
size_t octets_in_buffer,
size_t num_trials);
srtp_err_status_t srtp_cipher_type_alloc(const srtp_cipher_type_t *ct,
srtp_cipher_t **c,
size_t key_len,
size_t 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,
srtp_cipher_direction_t direction);
srtp_err_status_t srtp_cipher_output(srtp_cipher_t *c,
uint8_t *buffer,
size_t *num_octets_to_output);
srtp_err_status_t srtp_cipher_encrypt(srtp_cipher_t *c,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len);
srtp_err_status_t srtp_cipher_decrypt(srtp_cipher_t *c,
const uint8_t *src,
size_t src_len,
uint8_t *dst,
size_t *dst_len);
srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c,
const uint8_t *aad,
size_t aad_len);
/*
* srtp_replace_cipher_type(ct, id)
*
* replaces srtp's existing cipher implementation for the cipher_type id
* 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);
#ifdef __cplusplus
}
#endif
#endif /* SRTP_CIPHER_H */

View File

@@ -0,0 +1,62 @@
/*
*
* Copyright(c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef SRTP_CIHPER_PRIV_H
#define SRTP_CIHPER_PRIV_H
#include "cipher.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* A trivial platform independent random source.
* For use in test only.
*/
void srtp_cipher_rand_for_tests(uint8_t *dest, size_t len);
/*
* A trivial platform independent 32 bit random number.
* For use in test only.
*/
uint32_t srtp_cipher_rand_u32_for_tests(void);
#ifdef __cplusplus
}
#endif
#endif /* SRTP_CIPHER_PRIV_H */

View File

@@ -0,0 +1,80 @@
/*
*
* Copyright(c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef CIHPER_TYPES_H
#define CIHPER_TYPES_H
#include "cipher.h"
#include "auth.h"
/*
* cipher types that can be included in the kernel
*/
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 GCM
extern const srtp_cipher_type_t srtp_aes_icm_192;
extern const srtp_cipher_type_t srtp_aes_gcm_128;
extern const srtp_cipher_type_t srtp_aes_gcm_256;
#endif
/*
* auth func types that can be included in the kernel
*/
extern const srtp_auth_type_t srtp_null_auth;
extern const srtp_auth_type_t srtp_hmac;
/*
* 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_alloc;
/* debug modules for cipher types */
extern srtp_debug_module_t srtp_mod_aes_icm;
#if defined(OPENSSL) || defined(WOLFSSL) || defined(MBEDTLS) || defined(NSS)
extern srtp_debug_module_t srtp_mod_aes_gcm;
#endif
/* debug modules for auth types */
extern srtp_debug_module_t srtp_mod_hmac;
#endif

View File

@@ -0,0 +1,215 @@
/*
* crypto_kernel.h
*
* header for the cryptographic kernel
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright(c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef CRYPTO_KERNEL
#define CRYPTO_KERNEL
#include "cipher.h"
#include "auth.h"
#include "err.h"
#include "crypto_types.h"
#include "key.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* crypto_kernel_state_t defines the possible states:
*
* insecure - not yet initialized
* secure - initialized and passed self-tests
*/
typedef enum {
srtp_crypto_kernel_state_insecure,
srtp_crypto_kernel_state_secure
} srtp_crypto_kernel_state_t;
/*
* linked list of cipher types
*/
typedef struct srtp_kernel_cipher_type {
srtp_cipher_type_id_t id;
const srtp_cipher_type_t *cipher_type;
struct srtp_kernel_cipher_type *next;
} srtp_kernel_cipher_type_t;
/*
* linked list of auth types
*/
typedef struct srtp_kernel_auth_type {
srtp_auth_type_id_t id;
const srtp_auth_type_t *auth_type;
struct srtp_kernel_auth_type *next;
} srtp_kernel_auth_type_t;
/*
* linked list of debug modules
*/
typedef struct srtp_kernel_debug_module {
srtp_debug_module_t *mod;
struct srtp_kernel_debug_module *next;
} srtp_kernel_debug_module_t;
/*
* crypto_kernel_t is the data structure for the crypto kernel
*
* note that there is *exactly one* instance of this data type,
* 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_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
* crypto algorithms. Possible return values are:
*
* srtp_err_status_ok initialization successful
* <other> init failure
*
* If any value other than srtp_err_status_ok is returned, the
* crypto_kernel MUST NOT be used.
*/
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
* deallocates any dynamically allocated memory. Possible return
* values are:
*
* srtp_err_status_ok shutdown successful
* <other> shutdown failure
*
*/
srtp_err_status_t srtp_crypto_kernel_shutdown(void);
/*
* The function srtp_crypto_kernel_stats() checks the the crypto_kernel,
* running tests on the ciphers, auth funcs, and rng, and prints out a
* status report. Possible return values are:
*
* srtp_err_status_ok all tests were passed
* <other> a test failed
*
*/
srtp_err_status_t srtp_crypto_kernel_status(void);
/*
* srtp_crypto_kernel_list_debug_modules() outputs a list of debugging modules
*
*/
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_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_crypto_kernel_alloc_cipher(id, cp, key_len);
*
* allocates a cipher of type id at location *cp, with key length
* key_len octets. Return values are:
*
* srtp_err_status_ok no problems
* 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,
size_t key_len,
size_t tag_len);
/*
* srtp_crypto_kernel_alloc_auth(id, ap, key_len, tag_len);
*
* allocates an auth function of type id at location *ap, with key
* length key_len octets and output tag length of tag_len. Return
* values are:
*
* srtp_err_status_ok no problems
* 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,
size_t key_len,
size_t tag_len);
/*
* srtp_crypto_kernel_set_debug_module(mod_name, v)
*
* sets dynamic debugging to the value v (false for off, true for on) for the
* debug module with the name mod_name
*
* 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,
bool v);
#ifdef __cplusplus
}
#endif
#endif /* CRYPTO_KERNEL */

View File

@@ -0,0 +1,116 @@
/*
* crypto_types.h
*
* constants for cipher types and auth func types
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright(c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef SRTP_CRYPTO_TYPES_H
#define SRTP_CRYPTO_TYPES_H
/*
* The null cipher performs no encryption.
*
* 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
/*
* 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
/*
* 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
/*
* 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
/*
* AES-128_GCM Galois Counter Mode (AES GCM)
*
* 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
/*
* AES-256_GCM Galois Counter Mode (AES GCM)
*
* 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
/*
* 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
/*
* HMAC-SHA1
*
* SRTP_HMAC_SHA1 implements the Hash-based MAC using the NIST Secure
* Hash Algorithm version 1 (SHA1).
*/
#define SRTP_HMAC_SHA1 3
#endif /* SRTP_CRYPTO_TYPES_H */

View File

@@ -0,0 +1,264 @@
/*
* datatypes.h
*
* data types for bit vectors and finite fields
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef DATATYPES_H
#define DATATYPES_H
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#elif defined HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#if defined(__SSE2__)
#include <emmintrin.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_WIN32) || defined(WIN32)
#include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
typedef union {
uint8_t v8[16];
uint16_t v16[8];
uint32_t v32[4];
uint64_t v64[2];
} v128_t;
#define MAX_PRINT_STRING_LEN 1024
char *srtp_octet_string_hex_string(const void *str, size_t length);
char *v128_bit_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_left_shift(v128_t *x, size_t shift_index);
/*
* the following macros define the data manipulation functions
*
*/
#if defined(__SSE2__)
#define v128_set_to_zero(x) \
(_mm_storeu_si128((__m128i *)(x), _mm_setzero_si128()))
#define v128_copy(x, y) \
(_mm_storeu_si128((__m128i *)(x), _mm_loadu_si128((const __m128i *)(y))))
#define v128_xor(z, x, y) \
(_mm_storeu_si128((__m128i *)(z), \
_mm_xor_si128(_mm_loadu_si128((const __m128i *)(x)), \
_mm_loadu_si128((const __m128i *)(y)))))
#define v128_xor_eq(z, x) \
(_mm_storeu_si128((__m128i *)(z), \
_mm_xor_si128(_mm_loadu_si128((const __m128i *)(x)), \
_mm_loadu_si128((const __m128i *)(z)))))
#else /* defined(__SSE2__) */
#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_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_eq(z, x) \
((z)->v64[0] ^= (x)->v64[0], (z)->v64[1] ^= (x)->v64[1])
#endif /* defined(__SSE2__) */
/* NOTE! This assumes an odd ordering! */
/* This will not be compatible directly with math on some processors */
/* bit 0 is first 32-bit word, low order bit. in little-endian, that's
the first byte of the first 32-bit word. In big-endian, that's
the 3rd byte of the first 32-bit word */
/* The get/set bit code is used by the replay code ONLY, and it doesn't
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_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))))
/*
* srtp_octet_string_equal(a, b, len) returns true if the octet strings
* a and b are equal. It returns false otherwise. The running time of the
* comparison depends only on length, making this safe to use for (e.g.)
* verifying authentication tags.
*/
bool srtp_octet_string_equal(const uint8_t *a, const uint8_t *b, size_t 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);
/*
* 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);
#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)
#elif defined(HAVE_BYTESWAP_H)
/* We have (hopefully) optimized versions in byteswap.h */
#include <byteswap.h>
#define be32_to_cpu(x) bswap_32((x))
#define be64_to_cpu(x) bswap_64((x))
#elif defined(__APPLE__)
// Mac OS X / Darwin features
#include <libkern/OSByteOrder.h>
#define be32_to_cpu(x) OSSwapInt32(x)
#define be64_to_cpu(x) OSSwapInt64(x)
#else /* WORDS_BIGENDIAN */
#if defined(__GNUC__)
/* Fall back. */
static inline uint32_t be32_to_cpu(uint32_t v)
{
return __builtin_bswap32(v);
}
#else /* HAVE_X86 */
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#elif defined HAVE_WINSOCK2_H
#include <winsock2.h>
#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)
{
#if defined(__GNUC__)
v = __builtin_bswap64(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;
}
#endif /* WORDS_BIGENDIAN */
#endif /* HAVE_CONFIG_H */
/*
* 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 bytes_per_word 4
typedef struct {
size_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_set_bit(v, bit_index) \
((((v)->word[((bit_index) >> 5)] |= ((uint32_t)1 << ((bit_index)&31)))))
#define bitvector_get_length(v) (((v)->length))
bool bitvector_alloc(bitvector_t *v, size_t length);
void bitvector_dealloc(bitvector_t *v);
void bitvector_set_to_zero(bitvector_t *x);
void bitvector_left_shift(bitvector_t *x, size_t index);
#ifdef __cplusplus
}
#endif
#endif /* DATATYPES_H */

View File

@@ -0,0 +1,171 @@
/*
* err.h
*
* error status codes
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef ERR_H
#define ERR_H
#include <stdio.h>
#include <stdarg.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "srtp.h"
#if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
#if __has_attribute(format)
#define LIBSRTP_FORMAT_PRINTF(fmt, args) \
__attribute__((format(__printf__, fmt, args)))
#else
#define LIBSRTP_FORMAT_PRINTF(fmt, args)
#endif
#else
#define LIBSRTP_FORMAT_PRINTF(fmt, args)
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup Error Error Codes
*
* Error status codes are represented by the enumeration srtp_err_status_t.
*
* @{
*/
/**
* @}
*/
typedef enum {
srtp_err_level_error,
srtp_err_level_warning,
srtp_err_level_info,
srtp_err_level_debug
} srtp_err_reporting_level_t;
/*
* err_reporting_init prepares the error system. If
* ERR_REPORTING_STDOUT is defined, it will log to stdout.
*
*/
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);
srtp_err_status_t srtp_install_err_report_handler(
srtp_err_report_handler_func_t func);
/*
* srtp_err_report reports a 'printf' formatted error
* string, followed by a an arg list. The level argument
* is one of srtp_err_reporting_level_t.
*
* Errors will be reported to stdout, if ERR_REPORTING_STDOUT
* is defined.
*
*/
void srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...)
LIBSRTP_FORMAT_PRINTF(2, 3);
/*
* debug_module_t defines a debug module
*/
typedef struct {
bool on; /* true if debugging is on, false if it is off */
const char *name; /* printable name for debug module */
} srtp_debug_module_t;
#ifdef ENABLE_DEBUG_LOGGING
#ifndef debug_print0
#define debug_print0(mod, format) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name)
#endif
#ifndef debug_print
#define debug_print(mod, format, arg) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg)
#endif
#ifndef debug_print2
#define debug_print2(mod, format, arg1, arg2) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, \
arg1, arg2)
#endif
#else
#ifndef debug_print0
#define debug_print0(mod, format) \
if (mod.on) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name)
#endif
#ifndef debug_print
#define debug_print(mod, format, arg) \
if (mod.on) \
srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg)
#endif
#ifndef debug_print2
#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
#endif
#ifdef __cplusplus
}
#endif
#endif /* ERR_H */

View File

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

View File

@@ -0,0 +1,86 @@
/*
* key.h
*
* key usage limits enforcement
*
* David A. Mcgrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef KEY_H
#define KEY_H
#include "rdbx.h" /* for srtp_xtd_seq_num_t */
#include "err.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct srtp_key_limit_ctx_t *srtp_key_limit_t;
typedef enum {
srtp_key_event_normal,
srtp_key_event_soft_limit,
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_clone(srtp_key_limit_t original,
srtp_key_limit_t *new_key);
srtp_key_event_t srtp_key_limit_update(srtp_key_limit_t key);
typedef enum {
srtp_key_state_normal,
srtp_key_state_past_soft_limit,
srtp_key_state_expired
} srtp_key_state_t;
typedef struct srtp_key_limit_ctx_t {
srtp_xtd_seq_num_t num_left;
srtp_key_state_t state;
} srtp_key_limit_ctx_t;
#ifdef __cplusplus
}
#endif
#endif /* KEY_H */

View File

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

View File

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

View File

@@ -0,0 +1,122 @@
/*
* replay-database.h
*
* interface for a replay database for packet security
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef REPLAY_DB_H
#define REPLAY_DB_H
#include "datatypes.h" /* for v128_t */
#include "err.h" /* for srtp_err_status_t */
#ifdef __cplusplus
extern "C" {
#endif
/*
* if the ith least significant bit is one, then the packet index
* window_end-i is in the database
*/
typedef struct {
uint32_t window_start; /* packet index of the first bit in bitmask */
v128_t bitmask;
} srtp_rdb_t;
/*
* srtp_rdb_init
*
* initalizes rdb
*
* returns srtp_err_status_ok on success, srtp_err_status_t_fail otherwise
*/
srtp_err_status_t srtp_rdb_init(srtp_rdb_t *rdb);
/*
* srtp_rdb_check
*
* checks to see if index appears in rdb
*
* returns srtp_err_status_fail if the index already appears in rdb,
* returns srtp_err_status_ok otherwise
*/
srtp_err_status_t srtp_rdb_check(const srtp_rdb_t *rdb, uint32_t rdb_index);
/*
* srtp_rdb_add_index
*
* adds index to srtp_rdb_t (and does *not* check if index appears in db)
*
* returns srtp_err_status_ok on success, srtp_err_status_fail otherwise
*
*/
srtp_err_status_t srtp_rdb_add_index(srtp_rdb_t *rdb, uint32_t rdb_index);
/*
* the functions srtp_rdb_increment() and srtp_rdb_get_value() are for use by
* senders, not receivers - DO NOT use these functions on the same
* 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
*
* return values:
*
* srtp_err_status_ok no problem
* srtp_err_status_key_expired sequence number too high
*
*/
srtp_err_status_t srtp_rdb_increment(srtp_rdb_t *rdb);
/*
* srtp_rdb_get_value(db) returns the current sequence number of db
*/
uint32_t srtp_rdb_get_value(const srtp_rdb_t *rdb);
#ifdef __cplusplus
}
#endif
#endif /* REPLAY_DB_H */

View File

@@ -0,0 +1,209 @@
/*
* rdbx.h
*
* replay database with extended packet indices, using a rollover counter
*
* David A. McGrew
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef RDBX_H
#define RDBX_H
#include "datatypes.h"
#include "err.h"
#ifdef __cplusplus
extern "C" {
#endif
/* #define ROC_TEST */
#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 */
#else /* use small seq_num and roc datatypes for testing purposes */
typedef uint8_t srtp_sequence_number_t; /* 8 bit sequence number */
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)))
/*
* An rtp_xtd_seq_num_t is a 64-bit unsigned integer used as an 'extended'
* sequence number.
*/
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.
*/
typedef struct {
srtp_xtd_seq_num_t index;
bitvector_t bitmask;
} srtp_rdbx_t;
/*
* srtp_rdbx_init(rdbx_ptr, ws)
*
* initializes the rdbx pointed to by its argument with the window size ws,
* setting the rollover counter and sequence number to zero
*/
srtp_err_status_t srtp_rdbx_init(srtp_rdbx_t *rdbx, size_t ws);
/*
* srtp_rdbx_dealloc(rdbx_ptr)
*
* frees memory associated with the rdbx
*/
srtp_err_status_t srtp_rdbx_dealloc(srtp_rdbx_t *rdbx);
/*
* srtp_rdbx_estimate_index(rdbx, guess, s)
*
* given an rdbx and a sequence number s (from a newly arrived packet),
* sets the contents of *guess to contain the best guess of the packet
* index to which s corresponds, and returns the difference between
* *guess and the locally stored synch info
*/
ssize_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);
*
* srtp_rdbx_check(&r, delta) checks to see if the xtd_seq_num_t
* which is at rdbx->window_start + delta is in the rdb
*
*/
srtp_err_status_t srtp_rdbx_check(const srtp_rdbx_t *rdbx, ssize_t difference);
/*
* srtp_replay_add_index(rdbx, delta)
*
* adds the srtp_xtd_seq_num_t at rdbx->window_start + delta to replay_db
* (and does *not* check if that xtd_seq_num_t appears in db)
*
* this function should be called *only* after replay_check has
* indicated that the index does not appear in the rdbx, and a mutex
* should protect the rdbx between these calls if necessary.
*/
srtp_err_status_t srtp_rdbx_add_index(srtp_rdbx_t *rdbx, ssize_t 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
* the current 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(srtp_rdbx_t *rdbx, uint32_t roc);
/*
* srtp_rdbx_get_packet_index(rdbx) returns the value of the rollover counter
* 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 functions - these are *internal* functions of rdbx, and
* shouldn't be used to manipulate rdbx internal values. use the rdbx
* api instead!
*/
/*
* srtp_rdbx_get_ws(rdbx_ptr)
*
* gets the window size which was used to initialize the rdbx
*/
size_t 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)
*
* given a srtp_xtd_seq_num_t local (which represents the highest
* known-to-be-good index) and a sequence number s (from a newly
* arrived packet), sets the contents of *guess to contain the best
* guess of the packet index to which s corresponds, and returns the
* difference between *guess and *local
*/
ssize_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)
*
* Get the current rollover counter
*
*/
uint32_t srtp_rdbx_get_roc(const srtp_rdbx_t *rdbx);
/*
* srtp_rdbx_set_roc_seq(rdbx, roc, seq) initializes the srtp_rdbx_t at the
* location rdbx to have the rollover counter value roc and packet sequence
* number seq. If the new rollover counter value is less than the current
* 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);
#ifdef __cplusplus
}
#endif
#endif /* RDBX_H */

View File

@@ -0,0 +1,90 @@
/*
* sha1.h
*
* interface to the Secure Hash Algorithm v.1 (SHA-1), specified in
* FIPS 180-1
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef SHA1_H
#define SHA1_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "err.h"
#include "datatypes.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t H[5]; /* state vector */
uint32_t M[16]; /* message buffer */
size_t octets_in_buffer; /* octets of message in buffer */
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
*
* srtp_sha1_update(&ctx, msg, len) hashes the len octets starting at msg
* into the SHA1 context
*
* srtp_sha1_final(&ctx, output) performs the final processing of the SHA1
* context and writes the result to the 20 octets at output
*
*/
void srtp_sha1_init(srtp_sha1_ctx_t *ctx);
void srtp_sha1_update(srtp_sha1_ctx_t *ctx,
const uint8_t *M,
size_t octets_in_msg);
void srtp_sha1_final(srtp_sha1_ctx_t *ctx, uint32_t output[5]);
#ifdef __cplusplus
}
#endif
#endif /* SHA1_H */

View File

@@ -0,0 +1,95 @@
/*
* alloc.c
*
* 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
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "alloc.h"
#include "crypto_kernel.h"
#include <stdlib.h>
/* the debug module for memory allocation */
srtp_debug_module_t srtp_mod_alloc = {
false, /* debugging is off by default */
"alloc" /* printable name for module */
};
/*
* Nota bene: the debugging statements for srtp_crypto_alloc() and
* srtp_crypto_free() have identical prefixes, which include the addresses
* of the memory locations on which they are operating. This fact can
* be used to locate memory leaks, by turning on memory debugging,
* grepping for 'alloc', then matching alloc and free calls by
* address.
*/
void *srtp_crypto_alloc(size_t size)
{
void *ptr;
if (!size) {
return NULL;
}
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 %zu bytes)\n",
size);
}
return ptr;
}
void srtp_crypto_free(void *ptr)
{
debug_print(srtp_mod_alloc, "(location: %p) freed", ptr);
free(ptr);
}

View File

@@ -0,0 +1,560 @@
/*
* crypto_kernel.c
*
* header for the cryptographic kernel
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright(c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "crypto_kernel.h"
#include "cipher_types.h"
#include "alloc.h"
#include <stdlib.h>
/* the debug module for the crypto_kernel */
srtp_debug_module_t srtp_mod_crypto_kernel = {
false, /* debugging is off by default */
"crypto kernel" /* printable name for module */
};
/* crypto_kernel is a global variable, the only one of its datatype */
static srtp_crypto_kernel_t crypto_kernel = {
srtp_crypto_kernel_state_insecure, /* start off in insecure state */
NULL, /* no cipher types yet */
NULL, /* no auth types yet */
NULL /* no debug modules yet */
};
#define MAX_RNG_TRIALS 25
srtp_err_status_t srtp_crypto_kernel_init(void)
{
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
*/
return srtp_crypto_kernel_status();
}
/* initialize error reporting system */
status = srtp_err_reporting_init();
if (status) {
return status;
}
/* load debug modules */
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_crypto_kernel);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_auth);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_cipher);
if (status) {
return status;
}
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);
if (status) {
return status;
}
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);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_aes_icm);
if (status) {
return status;
}
#ifdef GCM
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,
SRTP_AES_GCM_128);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_gcm_256,
SRTP_AES_GCM_256);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_aes_gcm);
if (status) {
return status;
}
#endif
/* load auth func types */
status = srtp_crypto_kernel_load_auth_type(&srtp_null_auth, SRTP_NULL_AUTH);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_auth_type(&srtp_hmac, SRTP_HMAC_SHA1);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_hmac);
if (status) {
return status;
}
/* change state to secure */
crypto_kernel.state = srtp_crypto_kernel_state_secure;
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_status(void)
{
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;
/* 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, " 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);
exit(status);
}
srtp_err_report(srtp_err_level_info, "passed\n");
ctype = ctype->next;
}
/* 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, " 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);
exit(status);
}
srtp_err_report(srtp_err_level_info, "passed\n");
atype = atype->next;
}
srtp_crypto_kernel_list_debug_modules();
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_list_debug_modules(void)
{
srtp_kernel_debug_module_t *dm = crypto_kernel.debug_module_list;
/* describe each debug module */
srtp_err_report(srtp_err_level_info, "debug modules loaded:\n");
while (dm != NULL) {
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 {
srtp_err_report(srtp_err_level_info, "(off)\n");
}
dm = dm->next;
}
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_shutdown(void)
{
/*
* free dynamic memory used in crypto_kernel at present
*/
/* walk down cipher type list, freeing memory */
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",
ctype->cipher_type->description);
srtp_crypto_free(ctype);
}
/* walk down authetication module list, freeing memory */
while (crypto_kernel.auth_type_list != NULL) {
srtp_kernel_auth_type_t *atype = crypto_kernel.auth_type_list;
crypto_kernel.auth_type_list = atype->next;
debug_print(srtp_mod_crypto_kernel,
"freeing memory for authentication %s",
atype->auth_type->description);
srtp_crypto_free(atype);
}
/* walk down debug module list, freeing memory */
while (crypto_kernel.debug_module_list != NULL) {
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);
srtp_crypto_free(kdm);
}
/* return to insecure state */
crypto_kernel.state = srtp_crypto_kernel_state_insecure;
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,
bool replace)
{
srtp_kernel_cipher_type_t *ctype;
srtp_kernel_cipher_type_t *new_ctype = NULL;
srtp_err_status_t status;
/* defensive coding */
if (new_ct == NULL) {
return srtp_err_status_bad_param;
}
if (new_ct->id != id) {
return srtp_err_status_bad_param;
}
/* check cipher type by running self-test */
status = srtp_cipher_type_self_test(new_ct);
if (status) {
return status;
}
/* walk down list, checking if this type is in the list already */
ctype = crypto_kernel.cipher_type_list;
while (ctype != NULL) {
if (id == ctype->id) {
if (!replace) {
return srtp_err_status_bad_param;
}
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) {
return srtp_err_status_bad_param;
}
ctype = ctype->next;
}
/* 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));
if (new_ctype == NULL) {
return srtp_err_status_alloc_fail;
}
new_ctype->next = crypto_kernel.cipher_type_list;
/* set head of list to new cipher type */
crypto_kernel.cipher_type_list = new_ctype;
}
/* set fields */
new_ctype->cipher_type = new_ct;
new_ctype->id = id;
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)
{
return srtp_crypto_kernel_do_load_cipher_type(new_ct, id, false);
}
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, true);
}
srtp_err_status_t srtp_crypto_kernel_do_load_auth_type(
const srtp_auth_type_t *new_at,
srtp_auth_type_id_t id,
bool replace)
{
srtp_kernel_auth_type_t *atype;
srtp_kernel_auth_type_t *new_atype = NULL;
srtp_err_status_t status;
/* defensive coding */
if (new_at == NULL) {
return srtp_err_status_bad_param;
}
if (new_at->id != id) {
return srtp_err_status_bad_param;
}
/* check auth type by running self-test */
status = srtp_auth_type_self_test(new_at);
if (status) {
return status;
}
/* walk down list, checking if this type is in the list already */
atype = crypto_kernel.auth_type_list;
while (atype != NULL) {
if (id == atype->id) {
if (!replace) {
return srtp_err_status_bad_param;
}
status = srtp_auth_type_test(new_at, atype->auth_type->test_data);
if (status) {
return status;
}
new_atype = atype;
break;
} else if (new_at == atype->auth_type) {
return srtp_err_status_bad_param;
}
atype = atype->next;
}
/* 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));
if (new_atype == NULL) {
return srtp_err_status_alloc_fail;
}
new_atype->next = crypto_kernel.auth_type_list;
/* set head of list to new auth type */
crypto_kernel.auth_type_list = new_atype;
}
/* set fields */
new_atype->auth_type = new_at;
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)
{
return srtp_crypto_kernel_do_load_auth_type(new_at, id, false);
}
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, true);
}
const srtp_cipher_type_t *srtp_crypto_kernel_get_cipher_type(
srtp_cipher_type_id_t id)
{
srtp_kernel_cipher_type_t *ctype;
/* walk down list, looking for id */
ctype = crypto_kernel.cipher_type_list;
while (ctype != NULL) {
if (id == ctype->id) {
return ctype->cipher_type;
}
ctype = ctype->next;
}
/* haven't found the right one, indicate failure by returning NULL */
return NULL;
}
srtp_err_status_t srtp_crypto_kernel_alloc_cipher(srtp_cipher_type_id_t id,
srtp_cipher_pointer_t *cp,
size_t key_len,
size_t tag_len)
{
const srtp_cipher_type_t *ct;
/*
* if the crypto_kernel is not yet initialized, we refuse to allocate
* any ciphers - this is a bit extra-paranoid
*/
if (crypto_kernel.state != srtp_crypto_kernel_state_secure) {
return srtp_err_status_init_fail;
}
ct = srtp_crypto_kernel_get_cipher_type(id);
if (!ct) {
return srtp_err_status_fail;
}
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)
{
srtp_kernel_auth_type_t *atype;
/* walk down list, looking for id */
atype = crypto_kernel.auth_type_list;
while (atype != NULL) {
if (id == atype->id) {
return atype->auth_type;
}
atype = atype->next;
}
/* haven't found the right one, indicate failure by returning NULL */
return NULL;
}
srtp_err_status_t srtp_crypto_kernel_alloc_auth(srtp_auth_type_id_t id,
srtp_auth_pointer_t *ap,
size_t key_len,
size_t tag_len)
{
const srtp_auth_type_t *at;
/*
* if the crypto_kernel is not yet initialized, we refuse to allocate
* any auth functions - this is a bit extra-paranoid
*/
if (crypto_kernel.state != srtp_crypto_kernel_state_secure) {
return srtp_err_status_init_fail;
}
at = srtp_crypto_kernel_get_auth_type(id);
if (!at) {
return srtp_err_status_fail;
}
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_kernel_debug_module_t *kdm, *new;
/* defensive coding */
if (new_dm == NULL || new_dm->name == NULL) {
return srtp_err_status_bad_param;
}
/* walk down list, checking if this type is in the list already */
kdm = crypto_kernel.debug_module_list;
while (kdm != NULL) {
if (strncmp(new_dm->name, kdm->mod->name, 64) == 0) {
return srtp_err_status_bad_param;
}
kdm = kdm->next;
}
/* 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));
if (new == NULL) {
return srtp_err_status_alloc_fail;
}
/* set fields */
new->mod = new_dm;
new->next = crypto_kernel.debug_module_list;
/* set head of list to new cipher type */
crypto_kernel.debug_module_list = new;
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_set_debug_module(const char *name, bool on)
{
srtp_kernel_debug_module_t *kdm;
/* walk down list, checking if this type is in the list already */
kdm = crypto_kernel.debug_module_list;
while (kdm != NULL) {
if (strncmp(name, kdm->mod->name, 64) == 0) {
kdm->mod->on = on;
return srtp_err_status_ok;
}
kdm = kdm->next;
}
return srtp_err_status_fail;
}

View File

@@ -0,0 +1,108 @@
/*
* err.c
*
* error status reporting functions
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright(c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "err.h"
#include "datatypes.h"
#include <string.h>
/* srtp_err_file is the FILE to which errors are reported */
static FILE *srtp_err_file = NULL;
srtp_err_status_t srtp_err_reporting_init(void)
{
#ifdef ERR_REPORTING_STDOUT
srtp_err_file = stdout;
#elif defined(ERR_REPORTING_FILE)
/* open file for error reporting */
srtp_err_file = fopen(ERR_REPORTING_FILE, "w");
if (srtp_err_file == NULL) {
return srtp_err_status_init_fail;
}
#endif
return srtp_err_status_ok;
}
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_report_handler = func;
return srtp_err_status_ok;
}
void srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...)
{
char msg[512];
va_list args;
if (srtp_err_file != NULL) {
va_start(args, format);
vfprintf(srtp_err_file, format, args);
va_end(args);
}
if (srtp_err_report_handler != NULL) {
va_start(args, 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';
}
srtp_err_report_handler(level, msg);
/*
* 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));
}
va_end(args);
}
}

View File

@@ -0,0 +1,90 @@
/*
* key.c
*
* key usage limits enforcement
*
* David A. Mcgrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "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)
{
if (s < soft_limit) {
return srtp_err_status_bad_param;
}
key->num_left = s;
key->state = srtp_key_state_normal;
return srtp_err_status_ok;
}
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;
}
*new_key = original;
return srtp_err_status_ok;
}
srtp_key_event_t srtp_key_limit_update(srtp_key_limit_t key)
{
key->num_left--;
if (key->num_left >= soft_limit) {
return srtp_key_event_normal; /* we're above the soft limit */
}
if (key->state == srtp_key_state_normal) {
/* we just passed the soft limit, so change the state */
key->state = srtp_key_state_past_soft_limit;
}
if (key->num_left < 1) {
/* we just hit the hard limit */
key->state = srtp_key_state_expired;
return srtp_key_event_hard_limit;
}
return srtp_key_event_soft_limit;
}

View File

@@ -0,0 +1,509 @@
/*
* datatypes.c
*
* data types for finite fields and functions for input, output, and
* manipulation
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "datatypes.h"
#include "alloc.h"
#ifdef OPENSSL
#include <openssl/crypto.h>
#endif
#if defined(__SSE2__)
#include <tmmintrin.h>
#endif
#if defined(_MSC_VER)
#define ALIGNMENT(N) __declspec(align(N))
#else
#define ALIGNMENT(N) __attribute__((aligned(N)))
#endif
/*
* bit_string is a buffer that is used to hold output strings, e.g.
* for printing.
*/
/* the value MAX_PRINT_STRING_LEN is defined in datatypes.h */
/* include space for null terminator */
static char bit_string[MAX_PRINT_STRING_LEN + 1];
static uint8_t srtp_nibble_to_hex_char(uint8_t nibble)
{
static const 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, size_t length)
{
const uint8_t *str = (const uint8_t *)s;
size_t i;
/* double length, since one octet takes two hex characters */
length *= 2;
/* truncate string if it would be too long */
if (length > MAX_PRINT_STRING_LEN) {
length = MAX_PRINT_STRING_LEN - 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;
}
char *v128_hex_string(v128_t *x)
{
size_t i, j;
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)
{
size_t 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])
{
#if defined(__SSE2__)
_mm_storeu_si128((__m128i *)(x), _mm_loadu_si128((const __m128i *)(s)));
#else
#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
#endif /* defined(__SSE2__) */
}
#if defined(__SSSE3__)
/* clang-format off */
ALIGNMENT(16)
static const uint8_t right_shift_masks[5][16] = {
{ 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u,
8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u },
{ 0x80, 0x80, 0x80, 0x80, 0u, 1u, 2u, 3u,
4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u },
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u },
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0u, 1u, 2u, 3u },
/* needed for bitvector_left_shift */
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }
};
ALIGNMENT(16)
static const uint8_t left_shift_masks[4][16] = {
{ 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u,
8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u },
{ 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u,
12u, 13u, 14u, 15u, 0x80, 0x80, 0x80, 0x80 },
{ 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
{ 12u, 13u, 14u, 15u, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }
};
/* clang-format on */
void v128_left_shift(v128_t *x, size_t shift)
{
if (shift > 127) {
v128_set_to_zero(x);
return;
}
const int base_index = shift >> 5;
const int bit_index = shift & 31;
__m128i mm = _mm_loadu_si128((const __m128i *)x);
__m128i mm_shift_right = _mm_cvtsi32_si128(bit_index);
__m128i mm_shift_left = _mm_cvtsi32_si128(32 - bit_index);
mm = _mm_shuffle_epi8(mm, ((const __m128i *)left_shift_masks)[base_index]);
__m128i mm1 = _mm_srl_epi32(mm, mm_shift_right);
__m128i mm2 = _mm_sll_epi32(mm, mm_shift_left);
mm2 = _mm_srli_si128(mm2, 4);
mm1 = _mm_or_si128(mm1, mm2);
_mm_storeu_si128((__m128i *)x, mm1);
}
#else /* defined(__SSSE3__) */
void v128_left_shift(v128_t *x, size_t shift)
{
const size_t base_index = shift >> 5;
const size_t bit_index = shift & 31;
if (shift > 127) {
v128_set_to_zero(x);
return;
}
if (bit_index == 0) {
for (size_t i = 0; i < 4 - base_index; i++) {
x->v32[i] = x->v32[i + base_index];
}
} else {
for (size_t 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 (size_t i = 4 - base_index; i < 4; i++) {
x->v32[i] = 0;
}
}
#endif /* defined(__SSSE3__) */
/* functions manipulating bitvector_t */
bool bitvector_alloc(bitvector_t *v, size_t length)
{
size_t l;
/* Round length up to a multiple of bits_per_word */
length = (length + bits_per_word - 1) & ~(size_t)((bits_per_word - 1));
l = length / bits_per_word * bytes_per_word;
l = (l + 15ul) & ~15ul;
/* allocate memory, then set parameters */
if (l == 0) {
v->word = NULL;
v->length = 0;
return false;
} else {
v->word = (uint32_t *)srtp_crypto_alloc(l);
if (v->word == NULL) {
v->length = 0;
return false;
}
}
v->length = length;
/* initialize bitvector to zero */
bitvector_set_to_zero(v);
return true;
}
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)
{
/* C99 guarantees that memset(0) will set the value 0 for uint32_t */
memset(x->word, 0, x->length >> 3);
}
#if defined(__SSSE3__)
void bitvector_left_shift(bitvector_t *x, size_t shift)
{
if ((uint32_t)shift >= x->length) {
bitvector_set_to_zero(x);
return;
}
const size_t base_index = shift >> 5;
const size_t bit_index = shift & 31;
const size_t vec_length = (x->length + 127u) >> 7;
const __m128i *from = ((const __m128i *)x->word) + (base_index >> 2);
__m128i *to = (__m128i *)x->word;
__m128i *const end = to + vec_length;
__m128i mm_right_shift_mask =
((const __m128i *)right_shift_masks)[4u - (base_index & 3u)];
__m128i mm_left_shift_mask =
((const __m128i *)left_shift_masks)[base_index & 3u];
__m128i mm_shift_right = _mm_cvtsi32_si128(bit_index);
__m128i mm_shift_left = _mm_cvtsi32_si128(32 - bit_index);
__m128i mm_current = _mm_loadu_si128(from);
__m128i mm_current_r = _mm_srl_epi32(mm_current, mm_shift_right);
__m128i mm_current_l = _mm_sll_epi32(mm_current, mm_shift_left);
while ((end - from) >= 2) {
++from;
__m128i mm_next = _mm_loadu_si128(from);
__m128i mm_next_r = _mm_srl_epi32(mm_next, mm_shift_right);
__m128i mm_next_l = _mm_sll_epi32(mm_next, mm_shift_left);
mm_current_l = _mm_alignr_epi8(mm_next_l, mm_current_l, 4);
mm_current = _mm_or_si128(mm_current_r, mm_current_l);
mm_current = _mm_shuffle_epi8(mm_current, mm_left_shift_mask);
__m128i mm_temp_next = _mm_srli_si128(mm_next_l, 4);
mm_temp_next = _mm_or_si128(mm_next_r, mm_temp_next);
mm_temp_next = _mm_shuffle_epi8(mm_temp_next, mm_right_shift_mask);
mm_current = _mm_or_si128(mm_temp_next, mm_current);
_mm_storeu_si128(to, mm_current);
++to;
mm_current_r = mm_next_r;
mm_current_l = mm_next_l;
}
mm_current_l = _mm_srli_si128(mm_current_l, 4);
mm_current = _mm_or_si128(mm_current_r, mm_current_l);
mm_current = _mm_shuffle_epi8(mm_current, mm_left_shift_mask);
_mm_storeu_si128(to, mm_current);
++to;
while (to < end) {
_mm_storeu_si128(to, _mm_setzero_si128());
++to;
}
}
#else /* defined(__SSSE3__) */
void bitvector_left_shift(bitvector_t *x, size_t shift)
{
const size_t base_index = shift >> 5;
const size_t bit_index = shift & 31;
const size_t word_length = x->length >> 5;
if (shift >= x->length) {
bitvector_set_to_zero(x);
return;
}
if (bit_index == 0) {
for (size_t i = 0; i < word_length - base_index; i++) {
x->word[i] = x->word[i + base_index];
}
} else {
for (size_t 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 (size_t i = word_length - base_index; i < word_length; i++) {
x->word[i] = 0;
}
}
#endif /* defined(__SSSE3__) */
bool srtp_octet_string_equal(const uint8_t *a, const uint8_t *b, size_t length)
{
/*
* 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.
*/
const uint8_t *end = b + length;
uint32_t accumulator = 0;
#if defined(__SSE2__)
__m128i mm_accumulator1 = _mm_setzero_si128();
__m128i mm_accumulator2 = _mm_setzero_si128();
for (size_t i = 0, n = length >> 5; i < n; ++i, a += 32, b += 32) {
__m128i mm_a1 = _mm_loadu_si128((const __m128i *)a);
__m128i mm_b1 = _mm_loadu_si128((const __m128i *)b);
__m128i mm_a2 = _mm_loadu_si128((const __m128i *)(a + 16));
__m128i mm_b2 = _mm_loadu_si128((const __m128i *)(b + 16));
mm_a1 = _mm_xor_si128(mm_a1, mm_b1);
mm_a2 = _mm_xor_si128(mm_a2, mm_b2);
mm_accumulator1 = _mm_or_si128(mm_accumulator1, mm_a1);
mm_accumulator2 = _mm_or_si128(mm_accumulator2, mm_a2);
}
mm_accumulator1 = _mm_or_si128(mm_accumulator1, mm_accumulator2);
if ((end - b) >= 16) {
__m128i mm_a1 = _mm_loadu_si128((const __m128i *)a);
__m128i mm_b1 = _mm_loadu_si128((const __m128i *)b);
mm_a1 = _mm_xor_si128(mm_a1, mm_b1);
mm_accumulator1 = _mm_or_si128(mm_accumulator1, mm_a1);
a += 16;
b += 16;
}
if ((end - b) >= 8) {
__m128i mm_a1 = _mm_loadl_epi64((const __m128i *)a);
__m128i mm_b1 = _mm_loadl_epi64((const __m128i *)b);
mm_a1 = _mm_xor_si128(mm_a1, mm_b1);
mm_accumulator1 = _mm_or_si128(mm_accumulator1, mm_a1);
a += 8;
b += 8;
}
mm_accumulator1 = _mm_or_si128(
mm_accumulator1, _mm_unpackhi_epi64(mm_accumulator1, mm_accumulator1));
mm_accumulator1 =
_mm_or_si128(mm_accumulator1, _mm_srli_si128(mm_accumulator1, 4));
accumulator = _mm_cvtsi128_si32(mm_accumulator1);
#else
uint32_t accumulator2 = 0;
for (size_t i = 0, n = length >> 3; i < n; ++i, a += 8, b += 8) {
uint32_t a_val1, b_val1;
uint32_t a_val2, b_val2;
memcpy(&a_val1, a, sizeof(a_val1));
memcpy(&b_val1, b, sizeof(b_val1));
memcpy(&a_val2, a + 4, sizeof(a_val2));
memcpy(&b_val2, b + 4, sizeof(b_val2));
accumulator |= a_val1 ^ b_val1;
accumulator2 |= a_val2 ^ b_val2;
}
accumulator |= accumulator2;
if ((end - b) >= 4) {
uint32_t a_val, b_val;
memcpy(&a_val, a, sizeof(a_val));
memcpy(&b_val, b, sizeof(b_val));
accumulator |= a_val ^ b_val;
a += 4;
b += 4;
}
#endif
while (b < end) {
accumulator |= (*a++ ^ *b++);
}
/* Return true if equal */
return accumulator == 0;
}
void srtp_cleanse(void *s, size_t len)
{
#if defined(__GNUC__)
memset(s, 0, len);
__asm__ __volatile__("" : : "r"(s) : "memory");
#else
volatile uint8_t *p = (volatile uint8_t *)s;
while (len--) {
*p++ = 0;
}
#endif
}
void octet_string_set_to_zero(void *s, size_t len)
{
#if defined(OPENSSL)
OPENSSL_cleanse(s, len);
#else
srtp_cleanse(s, len);
#endif
}

View File

@@ -0,0 +1,140 @@
/*
* rdb.c
*
* Implements a replay database for packet security
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "rdb.h"
#define rdb_bits_in_bitmask (8 * sizeof(v128_t))
/*
* this implementation of a replay database works as follows:
*
* window_start is the index of the first packet in the window
* bitmask a bit-buffer, containing the most recently entered
* index as the leftmost bit
*
*/
/* srtp_rdb_init initalizes rdb */
srtp_err_status_t srtp_rdb_init(srtp_rdb_t *rdb)
{
v128_set_to_zero(&rdb->bitmask);
rdb->window_start = 0;
return srtp_err_status_ok;
}
/*
* 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)
{
/* 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;
}
/* if the index appears before the window, its bad */
if (p_index < rdb->window_start) {
return srtp_err_status_replay_old;
}
/* otherwise, the index appears within the window, so check the bitmask */
if (v128_get_bit(&rdb->bitmask, (p_index - rdb->window_start)) == 1) {
return srtp_err_status_replay_fail;
}
/* otherwise, the index is okay */
return srtp_err_status_ok;
}
/*
* srtp_rdb_add_index adds index to srtp_rdb_t (and does *not* check if
* index appears in db)
*
* this function should be called only after srtp_rdb_check has
* 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)
{
uint32_t delta;
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)
{
if (rdb->window_start >= 0x7fffffff) {
return srtp_err_status_key_expired;
}
++rdb->window_start;
return srtp_err_status_ok;
}
uint32_t srtp_rdb_get_value(const srtp_rdb_t *rdb)
{
return rdb->window_start;
}

View File

@@ -0,0 +1,338 @@
/*
* rdbx.c
*
* a replay database with extended range, using a rollover counter
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "rdbx.h"
/*
* from RFC 3711:
*
* A receiver reconstructs the index i of a packet with sequence
* number SEQ using the estimate
*
* i = 2^16 * v + SEQ,
*
* where v is chosen from the set { ROC-1, ROC, ROC+1 } such that i is
* closest to the value 2^16 * ROC + s_l. If the value r+1 is used,
* then the rollover counter r in the cryptographic context is
* incremented by one (if the packet containing s is authentic).
*/
/*
* rdbx implementation notes
*
* A srtp_xtd_seq_num_t is essentially a sequence number for which some of
* the data on the wire are implicit. It logically consists of a
* rollover counter and a sequence number; the sequence number is the
* explicit part, and the rollover counter is the implicit part.
*
* Upon receiving a sequence_number (e.g. in a newly received SRTP
* packet), the complete srtp_xtd_seq_num_t can be estimated by using a
* local srtp_xtd_seq_num_t as a basis. This is done using the function
* srtp_index_guess(&local, &guess, seq_from_packet). This function
* returns the difference of the guess and the local value. The local
* srtp_xtd_seq_num_t can be moved forward to the guess using the function
* 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
* 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)
{
*pi = 0;
}
void srtp_index_advance(srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s)
{
*pi += s;
}
/*
* srtp_index_guess(local, guess, s)
*
* given a srtp_xtd_seq_num_t local (which represents the last
* known-to-be-good received srtp_xtd_seq_num_t) and a sequence number s
* (from a newly arrived packet), sets the contents of *guess to
* contain the best guess of the packet index to which s corresponds,
* and returns the difference between *guess and *local
*
* nota bene - the output is a signed integer, DON'T cast it to a
* unsigned integer!
*/
ssize_t srtp_index_guess(const srtp_xtd_seq_num_t *local,
srtp_xtd_seq_num_t *guess,
srtp_sequence_number_t s)
{
uint32_t local_roc = (uint32_t)(*local >> 16);
uint16_t local_seq = (uint16_t)*local;
uint32_t guess_roc;
uint16_t guess_seq;
ssize_t difference;
if (local_seq < seq_num_median) {
if (s - local_seq > seq_num_median) {
guess_roc = local_roc - 1;
difference = s - local_seq - seq_num_max;
} else {
guess_roc = local_roc;
difference = s - local_seq;
}
} else {
if (local_seq - seq_num_median > s) {
guess_roc = local_roc + 1;
difference = s - local_seq + seq_num_max;
} else {
guess_roc = local_roc;
difference = s - local_seq;
}
}
guess_seq = s;
/* Note: guess_roc is 32 bits, so this generates a 48-bit result! */
*guess = (((uint64_t)guess_roc) << 16) | guess_seq;
return difference;
}
/*
* rdbx
*
*/
/*
* 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, size_t ws)
{
if (ws == 0) {
return srtp_err_status_bad_param;
}
if (!bitvector_alloc(&rdbx->bitmask, ws)) {
return srtp_err_status_alloc_fail;
}
srtp_index_init(&rdbx->index);
return srtp_err_status_ok;
}
/*
* 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)
{
bitvector_dealloc(&rdbx->bitmask);
return srtp_err_status_ok;
}
/*
* srtp_rdbx_set_roc(rdbx, roc) initializes the srtp_rdbx_t at the location rdbx
* to have the rollover counter value roc. If that value is less than
* the current 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(srtp_rdbx_t *rdbx, uint32_t roc)
{
bitvector_set_to_zero(&rdbx->bitmask);
/* make sure that we're not moving backwards */
if (roc < (rdbx->index >> 16)) {
return srtp_err_status_replay_old;
}
rdbx->index &= 0xffff; /* retain lowest 16 bits */
rdbx->index |= ((uint64_t)roc) << 16; /* set ROC */
return srtp_err_status_ok;
}
/*
* srtp_rdbx_get_packet_index(rdbx) returns the value of the packet index
* for the srtp_rdbx_t pointed to by rdbx
*
*/
srtp_xtd_seq_num_t srtp_rdbx_get_packet_index(const srtp_rdbx_t *rdbx)
{
return rdbx->index;
}
/*
* srtp_rdbx_get_window_size(rdbx) returns the value of the window size
* for the srtp_rdbx_t pointed to by rdbx
*
*/
size_t srtp_rdbx_get_window_size(const srtp_rdbx_t *rdbx)
{
return bitvector_get_length(&rdbx->bitmask);
}
/*
* 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, ssize_t delta)
{
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,
(bitvector_get_length(&rdbx->bitmask) - 1) +
delta) == 1) {
/* delta is within the window, so check the bitmask */
return srtp_err_status_replay_fail;
}
/* otherwise, the index is okay */
return srtp_err_status_ok;
}
/*
* srtp_rdbx_add_index adds the srtp_xtd_seq_num_t at rdbx->window_start + d to
* replay_db (and does *not* check if that srtp_xtd_seq_num_t appears in db)
*
* this function should be called only after replay_check has
* 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, ssize_t delta)
{
if (delta > 0) {
/* shift forward by delta */
srtp_index_advance(&rdbx->index, (srtp_sequence_number_t)delta);
bitvector_left_shift(&rdbx->bitmask, delta);
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);
}
/* note that we need not consider the case that delta == 0 */
return srtp_err_status_ok;
}
/*
* srtp_rdbx_estimate_index(rdbx, guess, s)
*
* given an rdbx and a sequence number s (from a newly arrived packet),
* sets the contents of *guess to contain the best guess of the packet
* index to which s corresponds, and returns the difference between
* *guess and the locally stored synch info
*/
ssize_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 (rdbx->index > seq_num_median) {
return srtp_index_guess(&rdbx->index, guess, s);
}
*guess = s;
return s - rdbx->index;
}
/*
* srtp_rdbx_get_roc(rdbx)
*
* Get the current rollover counter
*
*/
uint32_t srtp_rdbx_get_roc(const srtp_rdbx_t *rdbx)
{
uint32_t roc;
roc = (uint32_t)(rdbx->index >> 16);
return roc;
}
/*
* srtp_rdbx_set_roc_seq(rdbx, roc, seq) initializes the srtp_rdbx_t at the
* location rdbx to have the rollover counter value roc and packet sequence
* number seq. If the new rollover counter value is less than the current
* 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)
{
/* make sure that we're not moving backwards */
if (roc < (rdbx->index >> 16)) {
return srtp_err_status_replay_old;
}
rdbx->index = seq;
rdbx->index |= ((uint64_t)roc) << 16; /* set ROC */
bitvector_set_to_zero(&rdbx->bitmask);
return srtp_err_status_ok;
}

View File

@@ -0,0 +1,179 @@
/*
* aes_calc.c
*
* A simple AES calculator for generating AES encryption values
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
Example usage (with first NIST FIPS 197 test case):
[sh]$ test/aes_calc 000102030405060708090a0b0c0d0e0f \
00112233445566778899aabbccddeeff -v
plaintext: 00112233445566778899aabbccddeeff
key: 000102030405060708090a0b0c0d0e0f
ciphertext: 69c4e0d86a7b0430d8cdb78070b4c55a
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "aes.h"
#include "util.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void usage(char *prog_name)
{
printf("usage: %s <key> <plaintext> [<ciphertext>] [-v]\n", prog_name);
exit(255);
}
#define AES_MAX_KEY_LEN 32
int main(int argc, char *argv[])
{
const char *expected_ciphertext = NULL;
const char *ciphertext = NULL;
v128_t data;
uint8_t key[AES_MAX_KEY_LEN];
srtp_aes_expanded_key_t exp_key;
size_t key_len, len;
bool verbose = false;
srtp_err_status_t status;
/* -v must be last if it's passed */
if (argc > 0 && strncmp(argv[argc - 1], "-v", 2) == 0) {
/* we're in verbose mode */
verbose = true;
--argc;
}
if (argc < 3 || argc > 4) {
/* we've been fed the wrong number of arguments - compain and exit */
usage(argv[0]);
}
if (argc == 4) {
/* we're being passed the ciphertext to check (in unit test mode) */
expected_ciphertext = argv[3];
if (strlen(expected_ciphertext) != 16 * 2) {
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 %zu)\n",
AES_MAX_KEY_LEN * 2, strlen(argv[1]));
exit(1);
}
len = hex_string_to_octet_string(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 %zu)\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 %zu)\n",
16 * 2, strlen(argv[2]));
exit(1);
}
len = hex_string_to_octet_string((uint8_t *)&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 %zu)\n",
16 * 2, len);
exit(1);
}
if (verbose) {
/* print out plaintext */
printf("plaintext:\t%s\n",
octet_string_hex_string((uint8_t *)&data, 16));
}
/* 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);
}
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");
}
ciphertext = v128_hex_string(&data);
printf("%s\n", ciphertext);
if (expected_ciphertext && strcmp(ciphertext, expected_ciphertext) != 0) {
fprintf(stderr,
"error: calculated ciphertext %s does not match "
"expected ciphertext %s\n",
ciphertext, expected_ciphertext);
exit(1);
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,226 @@
/*
* datatypes_driver.c
*
* a test driver for crypto/math datatypes
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "datatypes.h"
#include "util.h"
#include <stdio.h> /* for printf() */
#include <string.h> /* for strlen() */
#include <stdlib.h>
void byte_order(void);
void test_hex_string_funcs(void);
void print_string(char *s);
void test_bswap(void);
void test_set_to_zero(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
*/
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();
for (size_t 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);
for (size_t 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, 127);
for (size_t i = 0; i < 128; i++) {
printf("%s\n", v128_bit_string(&x));
v128_left_shift(&x, 1);
}
printf("----------------------------------------------\n");
for (size_t 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 (size_t i = 0; i < 128; i += 2) {
v128_set_bit(&x, i);
}
printf("bit_string: { %s }\n", v128_bit_string(&x));
printf("get_bit: { ");
for (size_t i = 0; i < 128; i++) {
if (v128_get_bit(&x, i) == 1) {
printf("1");
} else {
printf("0");
}
}
printf(" } \n");
test_bswap();
test_set_to_zero();
return 0;
}
/* byte_order() prints out byte ordering of datatypes */
void byte_order(void)
{
size_t i;
v128_t e;
printf("byte ordering of crypto/math datatypes:\n");
for (i = 0; i < sizeof(e); i++) {
e.v8[i] = (uint8_t)i;
}
printf("v128_t: %s\n", v128_hex_string(&e));
}
void test_hex_string_funcs(void)
{
char hex1[] = "abadcafe";
char hex2[] = "0123456789abcdefqqqqq";
uint8_t raw[10];
size_t len;
len = hex_string_to_octet_string(raw, hex1, strlen(hex1));
printf("computed length: %zu\tstring: %s\n", len,
octet_string_hex_string(raw, len / 2));
printf("expected length: %zu\tstring: %s\n", strlen(hex1), hex1);
len = hex_string_to_octet_string(raw, hex2, strlen(hex2));
printf("computed length: %zu\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) = %zu\n", 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;
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;
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));
}
void test_set_to_zero(void)
{
#define BUFFER_SIZE (16)
uint8_t buffer[BUFFER_SIZE];
size_t i;
for (i = 0; i < BUFFER_SIZE; i++) {
buffer[i] = i & 0xff;
}
printf("Buffer before: %s\n", octet_string_hex_string(buffer, BUFFER_SIZE));
octet_string_set_to_zero(buffer, BUFFER_SIZE);
printf("Buffer after: %s\n", octet_string_hex_string(buffer, BUFFER_SIZE));
for (i = 0; i < BUFFER_SIZE; i++) {
if (buffer[i]) {
fprintf(stderr,
"Buffer contents not zero at position %zu (is %d)\n", i,
buffer[i]);
abort();
}
}
#undef BUFFER_SIZE
}

View File

@@ -0,0 +1,84 @@
/*
* env.c
*
* prints out a brief report on the build environment
*
* David McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017 Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdio.h>
#include <string.h> /* for srtcmp() */
#include "config.h"
int main(void)
{
size_t err_count = 0;
#ifdef WORDS_BIGENDIAN
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");
#endif
#ifdef CPU_RISC
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");
#else
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");
#endif
#ifdef ERR_REPORTING_STDOUT
printf("using stdout for error reporting\t(ERR_REPORTING_STDOUT == 1)\n");
#endif
if (err_count) {
printf("warning: configuration is probably in error "
"(found %zu problems)\n",
err_count);
}
return err_count;
}

View File

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

View File

@@ -0,0 +1,41 @@
# crypto test suite
test_apps = [
'cipher_driver',
'datatypes_driver',
'kernel_driver',
'env',
]
if not use_openssl and not use_wolfssl and not use_nss and not use_mbedtls
test_apps += ['sha1_driver']
endif
foreach test_name : test_apps
test_exe = executable(test_name,
'@0@.c'.format(test_name), '../../test/getopt_s.c', '../../test/util.c',
include_directories: [config_incs, crypto_incs, srtp3_incs, test_incs],
dependencies: [srtp3_deps, syslibs],
link_with: libsrtp3_for_tests)
test(test_name, test_exe, args: ['-v'])
endforeach
if not use_openssl and not use_wolfssl and not use_nss and not use_mbedtls
test_exe = executable('aes_calc',
'aes_calc.c', '../../test/getopt_s.c', '../../test/util.c',
include_directories: [config_incs, crypto_incs, srtp3_incs, test_incs],
dependencies: [srtp3_deps, syslibs],
link_with: libsrtp3_for_tests)
# data values used to test the aes_calc application for AES-128
k128 = '000102030405060708090a0b0c0d0e0f'
p128 = '00112233445566778899aabbccddeeff'
c128 = '69c4e0d86a7b0430d8cdb78070b4c55a'
test('aes_calc_128', test_exe, args: [k128, p128, c128])
# data values used to test the aes_calc application for AES-256
k256 = '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'
p256 = '00112233445566778899aabbccddeeff'
c256 = '8ea2b7ca516745bfeafc49904b496089'
test('aes_calc_256', test_exe, args: [k256, p256, c256])
endif

View File

@@ -0,0 +1,424 @@
/*
* sha1_driver.c
*
* a test driver for SHA-1
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017, Cisco Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* Neither the name of the Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "sha1.h"
#include "util.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SHA_PASS 0
#define SHA_FAIL 1
#define MAX_HASH_DATA_LEN 1024
#define MAX_HASH_OUT_LEN 20
typedef struct hash_test_case_t {
size_t data_len; /* number of octets in data */
size_t 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,
size_t data_len,
char *hex_hash,
size_t hash_len)
{
hash_test_case_t *list_head = *list_ptr;
hash_test_case_t *test_case;
size_t 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(test_case->data, hex_data, data_len * 2);
if (tmp_len != data_len * 2) {
free(test_case);
return srtp_err_status_parse_err;
}
tmp_len =
hex_string_to_octet_string(test_case->hash, hex_hash, hash_len * 2);
if (tmp_len != hash_len * 2) {
free(test_case);
return srtp_err_status_parse_err;
}
test_case->data_len = data_len;
test_case->hash_len = hash_len;
/* 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];
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;
}
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("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;
}
struct hex_sha1_test_case_t {
size_t bit_len;
char hex_data[MAX_HASH_DATA_LEN * 2];
char hex_hash[40 + 1];
};
srtp_err_status_t sha1_add_test_cases(void)
{
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
*/
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 (size_t 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;
}
}
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 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);
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;
}
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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
# Makefile for libSRTP documentation
#
# David A. McGrew
# Cisco Systems, Inc.
#
# This makefile does not use the autoconf system; we don't really need
# it. We just run doxygen.
# The most up to date documentation can be found at www.github.com/cisco/libsrtp
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
VPATH = @srcdir@
# Determine the version of the library
version = @PACKAGE_VERSION@
.PHONY: libsrtpdoc clean
libsrtpdoc:
@if test ! -e Doxyfile.in; then \
echo "*** Sorry, can't build doc outside source dir"; exit 1; \
fi
sed 's/@LIBSRTPVERSIONNUMBER@/$(version)/' Doxyfile.in > Doxyfile
doxygen
clean:
rm -rf html/ Doxyfile
for a in * ; do \
if [ -f "$$a~" ] ; then rm -f $$a~; fi; \
done;

View File

@@ -0,0 +1,74 @@
/**
@defgroup CryptoKernel Cryptographic Kernel
All of the cryptographic functions are contained in a kernel.
*/
/**
@defgroup CipherImplementations Ciphers
@ingroup CryptoKernel
@brief A generic cipher type enables cipher agility, that is, the
ability to write code that runs with multiple cipher types.
Ciphers can be used through the crypto kernel, or can be accessed
directly, if need be.
@{
*/
/**
* @brief Allocates a cipher of a particular type.
* @warning May be implemented as a macro.
*/
srtp_err_status_t srtp_cipher_type_alloc(const srtp_cipher_type_t *ct,
srtp_cipher_t **c,
size_t key_len,
size_t tlen);
/**
* @brief Initialized a cipher to use a particular key. May
* be invoked more than once on the same cipher.
* @warning May be implemented as a macro.
*/
srtp_err_status_t srtp_cipher_init(srtp_cipher_t *c, const uint8_t *key);
/**
* @brief Sets the initialization vector of a given cipher.
* @warning May be implemented as a macro.
*/
srtp_err_status_t srtp_cipher_set_iv(srtp_cipher_t *c,
uint8_t *iv,
srtp_cipher_direction_t direction);
/**
* @brief Encrypts a buffer with a given cipher.
* @warning May be implemented as a macro.
*/
srtp_err_status_t srtp_cipher_encrypt(srtp_cipher_t *c,
uint8_t *buffer,
size_t *num_octets_to_output);
/**
* @brief Sets a buffer to the keystream generated by the cipher.
* @warning May be implemented as a macro.
*/
srtp_err_status_t srtp_cipher_output(srtp_cipher_t *c,
uint8_t *buffer,
size_t *num_octets_to_output);
/**
* @brief Deallocates a cipher.
* @warning May be implemented as a macro.
*/
srtp_err_status_t srtp_cipher_dealloc(srtp_cipher_t *c);
/**
* @}
*/
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
# libSRTP documentation
doxygen = find_program('doxygen', required: get_option('doc'))
if not doxygen.found()
subdir_done()
endif
doc_config = configuration_data()
doc_config.set('LIBSRTPVERSIONNUMBER', meson.project_version())
doxyfile = configure_file(input: 'Doxyfile.in',
output: 'Doxyfile',
configuration: doc_config)
# can be built on demand with ninja -C builddir doc/html
doxygen_html_docs = custom_target('doc',
build_by_default: false,
command: [doxygen, doxyfile],
output: ['html'])
alias_target('libsrtp3doc', doxygen_html_docs)

35
src/libs/libsrtp/format.sh Executable file
View File

@@ -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-14
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 "Formatting 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

View File

@@ -0,0 +1,34 @@
# Makefile for libSRTP fuzzer
srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
VPATH = @srcdir@
CC = @CC@
CXX = @CXX@
INCDIR = -Iinclude -I$(srcdir)/include -I$(top_srcdir)/include -I$(top_srcdir)/crypto/include/
DEFS = @DEFS@
CPPFLAGS= @CPPFLAGS@ -g
CXXFLAGS= @CXXFLAGS@ -g
CFLAGS = @CFLAGS@ -g
LIBS = @LIBS@
COMPILE = $(CC) $(DEFS) $(INCDIR) $(CPPFLAGS) $(CFLAGS)
COMPILECXX = $(CXX) $(DEFS) $(INCDIR) $(CPPFLAGS) $(CXXFLAGS)
CRYPTOLIB = -lsrtp3
.PHONY: clean
all : srtp-fuzzer
mt19937.o: mt19937.cpp
$(COMPILECXX) -c -std=c++11 mt19937.cpp -o mt19937.o
fuzzer.o: fuzzer.c fuzzer.h testmem.h
$(COMPILE) fuzzer.c -c -o fuzzer.o
testmem.o: testmem.c
$(COMPILE) -O0 testmem.c -c -o testmem.o
srtp-fuzzer: fuzzer.o mt19937.o testmem.o
$(COMPILECXX) -L. -L.. fuzzer.o mt19937.o testmem.o $(LIBFUZZER) $(CRYPTOLIB) $(LIBS) -o srtp-fuzzer
clean:
rm -rf srtp-fuzzer *.o

View File

@@ -0,0 +1,88 @@
# libsrt fuzzer
By Guido Vranken <guidovranken@gmail.com> -- https://guidovranken.wordpress.com/
This is an advanced fuzzer for libSRTP (https://github.com/cisco/libsrtp). It implements several special techniques, described below, that are not often found in fuzzers or elsewhere. All are encouraged to transpose these ideas to their own fuzzers for the betterment of software security.
Feel free to contact me for business enquiries.
## Building
From the repository's root directory:
```sh
CC=clang CXX=clang++ CXXFLAGS="-fsanitize=fuzzer-no-link,address,undefined -g -O3" CFLAGS="-fsanitize=fuzzer-no-link,address,undefined -g -O3" LDFLAGS="-fsanitize=fuzzer-no-link,address,undefined" ./configure
LIBFUZZER="-fsanitize=fuzzer" make srtp-fuzzer
```
## Features
### Portable PRNG
```mt19937.c``` exports the C++11 Mersenne Twister implementaton. Hence, a modern C++ compiler is required to compile this file.
This approach has the following advantages:
- rand() is fickle -- its behavior eg. the sequence of numbers that it generates for a given seed, may differ across systems and libc's.
- C++11 mt19937 is portable, meaning that its behavior will be consistent across platforms. This is important to keep the fuzzing corpus portable.
- No need to implement a portable PRNG ourselves, or risk license incompatability by importing it from other projects.
### Size 0 allocations
To test whether allocations of size 0 eg. ```malloc(0)``` are ever dereferenced and written to, the custom allocater will return an intentionally invalid pointer pointer address for these requests.
For more information, see the comments in ```fuzz_alloc()```.
### Random allocation failures
The custom allocator will periodically return ```NULL``` for heap requests. This tests the library's resilience and correct operation in the event of global memory shortages.
The interval of ```NULL``` return values is deterministic as it relies on the PRNG, so for a given fuzzer input (that encodes the PRNG seed as well), behavior of that input with regards to allocator behaviour is consistent, allowing for reliable reproduction of bugs.
### Detecting inadequate pointer arithmetic
This feature is only available on 32 bit builds.
Unless the ```--no_mmap``` flag is given, the fuzzer will use a special allocation technique for some of the allocation requests. It will use ```mmap()``` to reserve memory at the extremities of the virtual address space -- sometimes at 0x00010000 and sometimes at 0xFFFF0000. This approach can assist in detecting invalid or inadequate pointer arithmetic. For example, consider the following code:
```c
if ( start + n < end ) {
memset(start, 0, n);
}
```
where ```start``` and ```end``` demarcate a memory region, and ```n``` is some positive integer.
If ```n``` is a sufficiently large value, a pointer addition overflow will occur, leading to a page fault. By routinely placing allocations at the high virtual address ```0xFFFF0000```, the chances of detecting this bug are increased. So let's say ```start``` was previously allocated at ```0xFFFF0000```, and ```end``` is ```0xFFFF1000```, and ```n``` is 0xFFFFF. Then the expression effectively becomes:
```c
if ( 0xFFFF0000 + 0x000FFFFF < 0xFFFF1000 ) {
memset(0xFFFF0000, 0, 0x000FFFF);
}
```
The addition ```0xFFFF0000 + 0x000FFFFF``` overflows so the result is ```0x000EFFFF```. Hence:
```c
if ( 0x000EFFFF < 0xFFFF1000 ) { // Expression resolves as true !
```
The subsequent ```memset``` is executed contrary to the programmer's intentions, and a segmentation fault will occur.
While this is a corner case, it can not be ruled out that it might occur in a production environment. What's more, the analyst examining the crash can reason about how the value of ```n``` comes about in the first place, and concoct a crafted input that leads to a very high ```n``` value, making the "exploit" succeed even with average virtual addresses.
Aside from using ```mmap``` to allocate at address ```0xFFFF0000```, the fuzzer will also place allocations at the low virtual address ```0x00010000``` to detect invalid pointer arithmetic involving subtraction:
```c
if ( end - n > start ) {
```
### Output memory testing
```testmem.c``` exports ```fuzz_testmem```. All this function does is copy the input buffer to a newly allocated heap region, and then free that heap region. If AddressSanitizer is enabled, this ensures that the input buffer to ```fuzz_testmem``` is a legal memory region.
If MemorySanitizer is enabled, then ``fuzz_testmem``` calls ```fuzz_testmem_msan````. The latter function writes the data at hand to ```/dev/null```. This is an nice trick to make MemorySanitizer evaluate this data, and crash if it contains uninitialized bytes.
This function has been implemented in a separate file for a reason: from the perspective of an optimizing compiler, this is a meaningless operation, and as such it might be optimized away. Hence, this file must be compiled without optimizations (```-O0``` flag).
## Contributing
When extending the current fuzzer, use variable types whose width is consistent across systems where possible. This is necessary to retain corpus portability. For example, use ```uint64_t``` rather than ```unsigned long```.

Some files were not shown because too many files have changed in this diff Show More