mirror of
https://github.com/espressif/esp-protocols.git
synced 2026-07-06 00:20:49 +02:00
feat(libsrtp): add component (libsrtp v2.8.0 + ESP-IDF mbedTLS port)
Adds libsrtp — an ESP-IDF wrapper around cisco/libsrtp pinned at v2.8.0
(commit 24b3bf8). Crypto routes through ESP-IDF's mbedTLS, so AES
protect/unprotect goes through the chip's on-chip AES peripheral by
default (CONFIG_MBEDTLS_HARDWARE_AES=y on esp32 / s2 / s3 / c3 / c5 /
c6 / p4). Pairs with libwebsockets and (upcoming) usrsctp for the
WebRTC transport stack.
The wrapper bundles cisco/libsrtp as a git submodule and compiles its
sources directly into the IDF component archive — no internal libsrtp2.a
dance. One small port-side delta in port/crypto_kernel.c opts out of
the AES-ICM-192 cipher registration when GCM is enabled (saves binary
size; AES-CM-128 + AES-GCM cover all WebRTC SRTP suites in use).
Naming + version follow cisco's release line. Component is named
'libsrtp' (registry: espressif/libsrtp) tracking whichever 2.x release
is current upstream — v2.8.0 today. The IDF version constraint
(>=5.4,<6) reflects the fact that libsrtp v2.x's mbedTLS adapters
predate the mbedTLS 4 / TF-PSA-Crypto split shipped by IDF v6; bump
when the component tracks a release that speaks mbedTLS 4.
Supported SRTP profiles via the mbedTLS backend:
AEAD: AEAD_AES_128_GCM, AEAD_AES_256_GCM
SRTP: AES_CM_128_HMAC_SHA1_80, AES_CM_128_HMAC_SHA1_32
Tests included:
test_apps/ — embedded Unity smoke (esp32 + esp32c3 via
.build-test-rules)
host_test/ — IDF Linux-target binary, AES-GCM-128 protect/
unprotect roundtrip; aborts on the first libsrtp
failure with EXPECT() for boolean assertions
examples/get_started/ — minimal init/shutdown sanity app
License: Apache-2.0 (port glue) AND BSD-3-Clause (bundled cisco/libsrtp).
(Previously prepared as espressif/idf-extra-components#753; relocated to
esp-protocols where it naturally sits alongside libwebsockets and the
other transport-stack components.)
This commit is contained in:
committed by
david-cermak
parent
67f205bb8e
commit
e5997168d9
@@ -0,0 +1,58 @@
|
||||
name: "libsrtp: build-tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, labeled]
|
||||
|
||||
jobs:
|
||||
build_libsrtp:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'libsrtp') || github.event_name == 'push'
|
||||
name: libsrtp build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
idf_ver: ["release-v5.4", "release-v5.5"]
|
||||
app:
|
||||
- { name: "get_started", path: "components/libsrtp/examples/get_started" }
|
||||
- { name: "test_apps", path: "components/libsrtp/test_apps" }
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build ${{ matrix.app.name }} with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
python -m pip install idf-build-apps
|
||||
python ./ci/build_apps.py -c ${{ matrix.app.path }} -m components/libsrtp/.build-test-rules.yml
|
||||
|
||||
host_test_libsrtp:
|
||||
if: contains(github.event.pull_request.labels.*.name, 'libsrtp') || github.event_name == 'push'
|
||||
name: libsrtp host test
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
idf_ver: ["release-v5.4", "release-v5.5"]
|
||||
runs-on: ubuntu-22.04
|
||||
container: espressif/idf:${{ matrix.idf_ver }}
|
||||
steps:
|
||||
- name: Checkout esp-protocols
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build + run host_test with IDF-${{ matrix.idf_ver }}
|
||||
shell: bash
|
||||
run: |
|
||||
. ${IDF_PATH}/export.sh
|
||||
python -m pip install idf-build-apps
|
||||
python ./ci/build_apps.py -c components/libsrtp/host_test -m components/libsrtp/.build-test-rules.yml
|
||||
cd components/libsrtp/host_test
|
||||
for dir in $(ls -d build_linux_* 2>/dev/null); do
|
||||
"./$dir/host_test_libsrtp.elf"
|
||||
done
|
||||
@@ -7,3 +7,6 @@
|
||||
[submodule "components/libwebsockets/libwebsockets"]
|
||||
path = components/libwebsockets/libwebsockets
|
||||
url = https://github.com/warmcat/libwebsockets.git
|
||||
[submodule "components/libsrtp/libsrtp"]
|
||||
path = components/libsrtp/libsrtp
|
||||
url = https://github.com/cisco/libsrtp.git
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
components/mosquitto/examples/serverless_mqtt/components/libjuice/port/juice_random.c
|
||||
components/libsrtp/port/crypto_kernel.c
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# libsrtp requires ESP-IDF 5.4+ (idf_component.yml `idf: ">=5.4"`). The
|
||||
# disable rules below skip the build on older IDF releases so the repo-wide
|
||||
# CI matrix (v5.1 / v5.2 / v5.3 / v5.4 / v5.5 / latest) doesn't try them.
|
||||
#
|
||||
# IDF v6+ is also disabled for now: libsrtp 2.x's mbedTLS adapters
|
||||
# (aes_gcm_mbedtls.c, aes_icm_mbedtls.c, hmac_mbedtls.c) include the
|
||||
# classic <mbedtls/aes.h> / <mbedtls/gcm.h> headers which moved under the
|
||||
# TF-PSA-Crypto split in mbedTLS 4.x (shipped by IDF v6+). Re-enable once
|
||||
# libsrtp adapts or we ship a port-side compatibility shim.
|
||||
|
||||
components/libsrtp/examples/get_started:
|
||||
enable:
|
||||
- if: IDF_TARGET in ["esp32", "esp32c3", "esp32s3", "esp32c5", "esp32c6", "esp32p4"]
|
||||
reason: "Build sanity on representative Xtensa + RISC-V targets."
|
||||
disable:
|
||||
- if: IDF_VERSION_MAJOR <= 5 and IDF_VERSION_MINOR < 4
|
||||
reason: "libsrtp requires ESP-IDF 5.4+."
|
||||
- if: IDF_VERSION_MAJOR >= 6
|
||||
reason: "libsrtp 2.x mbedTLS adapters not yet ported to mbedTLS 4.x (TF-PSA-Crypto split)."
|
||||
|
||||
components/libsrtp/test_apps:
|
||||
enable:
|
||||
- if: IDF_TARGET in ["esp32", "esp32c3"]
|
||||
reason: "Sufficient to exercise one Xtensa and one RISC-V target."
|
||||
disable:
|
||||
- if: IDF_VERSION_MAJOR <= 5 and IDF_VERSION_MINOR < 4
|
||||
reason: "libsrtp requires ESP-IDF 5.4+."
|
||||
- if: IDF_VERSION_MAJOR >= 6
|
||||
reason: "libsrtp 2.x mbedTLS adapters not yet ported to mbedTLS 4.x (TF-PSA-Crypto split)."
|
||||
|
||||
components/libsrtp/host_test:
|
||||
enable:
|
||||
- if: IDF_TARGET == "linux"
|
||||
reason: "Linux host build runs the SRTP roundtrip smoke test."
|
||||
disable:
|
||||
- if: IDF_VERSION_MAJOR <= 5 and IDF_VERSION_MINOR < 4
|
||||
reason: "libsrtp requires ESP-IDF 5.4+."
|
||||
- if: IDF_VERSION_MAJOR >= 6
|
||||
reason: "libsrtp 2.x mbedTLS adapters not yet ported to mbedTLS 4.x (TF-PSA-Crypto split)."
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
commitizen:
|
||||
bump_message: 'bump(libsrtp): $current_version -> $new_version'
|
||||
pre_bump_hooks: python ../../ci/changelog.py libsrtp
|
||||
tag_format: libsrtp-v$version
|
||||
version: 2.8.0
|
||||
version_files:
|
||||
- idf_component.yml
|
||||
@@ -0,0 +1,10 @@
|
||||
# Changelog
|
||||
|
||||
## [2.8.0](https://github.com/espressif/esp-protocols/commits/libsrtp-v2.8.0)
|
||||
|
||||
### Features
|
||||
|
||||
- First release. Tracks upstream cisco/libsrtp [`v2.8.0`](https://github.com/cisco/libsrtp/releases/tag/v2.8.0) (commit `24b3bf8`); component version follows upstream.
|
||||
- Wraps libsrtp as an ESP-IDF component using mbedTLS for AES-ICM, AES-GCM and HMAC-SHA1. ESP-IDF's mbedTLS routes AES through the on-chip AES peripheral by default (`CONFIG_MBEDTLS_HARDWARE_AES=y`), so SRTP protect/unprotect leverages hardware crypto with no wrapper-side code.
|
||||
- One small port-side delta in `port/crypto_kernel.c`: opts out of the AES-ICM-192 cipher registration when GCM is enabled (saves binary size; AES-CM-128 + AES-GCM cover all WebRTC SRTP suites).
|
||||
- Embedded smoke test (`test_apps/`) and host-side AES-GCM-128 protect/unprotect roundtrip test (`host_test/`) included.
|
||||
@@ -0,0 +1,79 @@
|
||||
# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set(SRTP_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/libsrtp")
|
||||
|
||||
# Vendored port-side source — replaces the upstream crypto/kernel/crypto_kernel.c
|
||||
# (which we exclude from SRCS below). The only delta vs upstream is opting out
|
||||
# of the AES-ICM-192 cipher registration when GCM is enabled, to save binary
|
||||
# size — AES-CM-128 + AES-GCM cover all WebRTC SRTP suites in use.
|
||||
#
|
||||
# Bundled into port/ rather than applied as a `git apply` patch at configure
|
||||
# time, so the wrapper works cleanly when installed via the IDF Component
|
||||
# Registry (the registry tarball has no .git dir for `git apply` to operate
|
||||
# on). Re-port from upstream when bumping the libsrtp submodule.
|
||||
set(SRTP_PORT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/port")
|
||||
|
||||
idf_component_register(
|
||||
SRCS "${SRTP_ROOT}/srtp/srtp.c"
|
||||
"${SRTP_ROOT}/crypto/cipher/aes_gcm_mbedtls.c"
|
||||
"${SRTP_ROOT}/crypto/cipher/aes_icm_mbedtls.c"
|
||||
"${SRTP_ROOT}/crypto/cipher/aes_icm.c"
|
||||
"${SRTP_ROOT}/crypto/cipher/aes.c"
|
||||
"${SRTP_ROOT}/crypto/cipher/cipher.c"
|
||||
"${SRTP_ROOT}/crypto/cipher/cipher_test_cases.c"
|
||||
"${SRTP_ROOT}/crypto/cipher/null_cipher.c"
|
||||
"${SRTP_ROOT}/crypto/hash/auth.c"
|
||||
"${SRTP_ROOT}/crypto/hash/hmac.c"
|
||||
"${SRTP_ROOT}/crypto/hash/hmac_mbedtls.c"
|
||||
"${SRTP_ROOT}/crypto/hash/auth_test_cases.c"
|
||||
"${SRTP_ROOT}/crypto/hash/null_auth.c"
|
||||
"${SRTP_ROOT}/crypto/hash/sha1.c"
|
||||
"${SRTP_PORT_DIR}/crypto_kernel.c" # replaces ${SRTP_ROOT}/crypto/kernel/crypto_kernel.c
|
||||
"${SRTP_ROOT}/crypto/kernel/alloc.c"
|
||||
"${SRTP_ROOT}/crypto/kernel/err.c"
|
||||
"${SRTP_ROOT}/crypto/kernel/key.c"
|
||||
"${SRTP_ROOT}/crypto/math/datatypes.c"
|
||||
"${SRTP_ROOT}/crypto/replay/rdb.c"
|
||||
"${SRTP_ROOT}/crypto/replay/rdbx.c"
|
||||
|
||||
PRIV_INCLUDE_DIRS
|
||||
"${SRTP_ROOT}/crypto/include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/port"
|
||||
INCLUDE_DIRS
|
||||
"${SRTP_ROOT}/include" # upstream API headers (srtp.h, ekt.h, ...)
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include" # srtp2/ namespace shim so consumers can still <srtp2/srtp.h>
|
||||
|
||||
REQUIRES "mbedtls"
|
||||
)
|
||||
|
||||
# Fully suppress (not just downgrade) warnings from third-party libsrtp
|
||||
# sources. The repo-wide CI pipeline runs idf-build-apps with strict
|
||||
# warning checking, so -Wno-error=* alone (which keeps the warning
|
||||
# printed) trips the matrix on otherwise-valid builds. We can't fix the
|
||||
# warnings upstream, so silence them here. Apple clang on IDF's Linux
|
||||
# target does not recognise -Wno-conflicting-types, so probe first.
|
||||
include(CheckCCompilerFlag)
|
||||
check_c_compiler_flag("-Wno-conflicting-types" SRTP2_HAS_NO_CONFLICTING_TYPES)
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE
|
||||
-Wno-format
|
||||
-Wno-unused-function
|
||||
-Wno-unused-variable
|
||||
-Wno-unused-but-set-variable
|
||||
-Wno-sign-compare
|
||||
-Wno-type-limits
|
||||
-Wno-pointer-sign
|
||||
-Wno-implicit-function-declaration
|
||||
-Wno-strict-prototypes
|
||||
-Wno-old-style-definition
|
||||
-Wno-incompatible-pointer-types
|
||||
)
|
||||
if(SRTP2_HAS_NO_CONFLICTING_TYPES)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-conflicting-types)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${COMPONENT_LIB} PUBLIC
|
||||
-DHAVE_CONFIG_H
|
||||
)
|
||||
@@ -0,0 +1,14 @@
|
||||
menu "libsrtp (libsrtp)"
|
||||
|
||||
# The ESP-IDF port wires libsrtp's crypto exclusively through mbedTLS
|
||||
# (AES-CM, AES-GCM, HMAC-SHA1). No Kconfig knob — the alternative
|
||||
# backends (OpenSSL, NSS, WolfSSL) aren't built in this component.
|
||||
|
||||
config SRTP2_LOG_RTP_TRACE
|
||||
bool "Enable verbose RTP trace logging"
|
||||
default n
|
||||
help
|
||||
Enables libsrtp's internal debug-trace logging at runtime
|
||||
(extra binary size; meant only for development).
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,175 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
@@ -0,0 +1,17 @@
|
||||
libsrtp
|
||||
Copyright 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
|
||||
This product includes software developed by the following third parties:
|
||||
|
||||
================================================================================
|
||||
|
||||
libsrtp
|
||||
https://github.com/cisco/libsrtp
|
||||
Copyright (c) 2001-2017, Cisco Systems, Inc.
|
||||
Licensed under the BSD 3-Clause License (see libsrtp/LICENSE).
|
||||
|
||||
The Secure Real-time Transport Protocol (SRTP) and Secure RTCP (SRTCP)
|
||||
implementation. Bundled as a submodule, pinned at upstream release tag
|
||||
v2.8.0 (commit 24b3bf8).
|
||||
|
||||
================================================================================
|
||||
@@ -0,0 +1,46 @@
|
||||
# libsrtp
|
||||
|
||||
[](https://components.espressif.com/components/espressif/libsrtp)
|
||||
|
||||
[libsrtp](https://github.com/cisco/libsrtp) (Cisco) port for ESP-IDF using the mbedtls crypto backend with AES-GCM.
|
||||
|
||||
Used for SRTP/SRTCP packet protection in WebRTC and other RTP-based protocols on ESP32-series chips.
|
||||
|
||||
> **Not the same as `espressif/esp_libsrtp`.** The existing `espressif/esp_libsrtp` component is a pre-built closed-source libSRTP binary distributed via `esp-adf-libs` (Custom license). `libsrtp` is an open-source wrapper around upstream [`cisco/libsrtp` 2.x](https://github.com/cisco/libsrtp) — built from source as part of your project, BSD-3-Clause upstream + Apache-2.0 port code. Pick `libsrtp` when you need the source-built, open-source path (e.g. for WebRTC integrations); pick `esp_libsrtp` when you're already on the ADF binary stack.
|
||||
|
||||
## Features
|
||||
|
||||
- libsrtp [`v2.8.0`](https://github.com/cisco/libsrtp/releases/tag/v2.8.0) (commit `24b3bf8`)
|
||||
- mbedtls crypto backend (AES-CM, AES-GCM, HMAC-SHA1) — IDF's mbedTLS routes AES through the on-chip AES peripheral when `CONFIG_MBEDTLS_HARDWARE_AES=y` (default)
|
||||
- AEAD profiles: `AEAD_AES_128_GCM`, `AEAD_AES_256_GCM`
|
||||
- SRTP profiles: `AES_CM_128_HMAC_SHA1_80`, `AES_CM_128_HMAC_SHA1_32`
|
||||
|
||||
## Add to a project
|
||||
|
||||
```bash
|
||||
idf.py add-dependency "espressif/libsrtp^2.8.0"
|
||||
```
|
||||
|
||||
Or in your project's `main/idf_component.yml`:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
espressif/libsrtp: "^2.8.0"
|
||||
```
|
||||
|
||||
Requires ESP-IDF ≥ 5.4.
|
||||
|
||||
## Tests
|
||||
|
||||
- `test_apps/` — embedded Unity smoke test (init/shutdown + version). Run with
|
||||
`pytest_libsrtp.py` against `esp32` / `esp32c3`.
|
||||
- `host_test/` — IDF Linux-target binary that performs an AES-GCM-128
|
||||
protect/unprotect roundtrip. Run with `pytest_libsrtp_linux.py`.
|
||||
|
||||
## Source
|
||||
|
||||
This wrapper bundles [cisco/libsrtp](https://github.com/cisco/libsrtp) as a git submodule pinned at the upstream release tag. All SRTP cryptographic implementation is upstream; this repo adds only the ESP-IDF build glue (`CMakeLists.txt`, `port/config.h`) plus one small port-side delta in `port/crypto_kernel.c` (replaces the upstream `crypto/kernel/crypto_kernel.c`) to opt out of the AES-ICM-192 cipher registration when GCM is enabled. Re-port from upstream when bumping the libsrtp submodule.
|
||||
|
||||
## License
|
||||
|
||||
`Apache-2.0 AND BSD-3-Clause` — the ESP-IDF port glue under this repo (`CMakeLists.txt`, `port/`, `Kconfig`, build scripts) is Apache-2.0 (see `LICENSE`); the bundled `libsrtp/` submodule remains under upstream's BSD-3-Clause (see `libsrtp/LICENSE`).
|
||||
@@ -0,0 +1,7 @@
|
||||
# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(libsrtp_get_started)
|
||||
@@ -0,0 +1,18 @@
|
||||
# libsrtp — get_started
|
||||
|
||||
Minimal sanity-check application for [`libsrtp`](https://github.com/espressif/idf-extra-components/tree/master/libsrtp). Initializes libsrtp via `srtp_init()` and shuts it down. Used by the repo's CI to verify the component compiles and links across supported targets; also useful as a copy-paste starting point.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
idf.py set-target esp32p4 # or esp32, esp32s3, esp32c3, esp32c6
|
||||
idf.py build
|
||||
idf.py -p <PORT> flash monitor
|
||||
```
|
||||
|
||||
The example consumes the parent component via `override_path: ../../..` in `main/idf_component.yml`, so it always tracks the in-tree source. Replace with a registry version to consume the published component instead:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
espressif/libsrtp: "^2.8.0"
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
# SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
idf_component_register(
|
||||
SRCS "main.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES libsrtp
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
## Build-check app for libsrtp.
|
||||
## During CI / local build, override_path points at the parent repo so we
|
||||
## consume the in-tree component instead of the registry version.
|
||||
dependencies:
|
||||
espressif/libsrtp:
|
||||
version: "^2.8.0"
|
||||
override_path: ../../..
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Minimal sanity-check app for libsrtp: initializes and shuts down libsrtp.
|
||||
* Used by .github/workflows/build.yml to verify the component compiles and
|
||||
* links across supported ESP-IDF targets.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "esp_log.h"
|
||||
#include "srtp2/srtp.h"
|
||||
|
||||
static const char *TAG = "libsrtp_check";
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
srtp_err_status_t status = srtp_init();
|
||||
if (status == srtp_err_status_ok) {
|
||||
ESP_LOGI(TAG, "srtp_init() OK");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "srtp_init() failed: %d", status);
|
||||
}
|
||||
srtp_shutdown();
|
||||
ESP_LOGI(TAG, "libsrtp build check complete");
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(COMPONENTS main)
|
||||
set(EXTRA_COMPONENT_DIRS "..")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(host_test_libsrtp)
|
||||
@@ -0,0 +1,8 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
idf_component_register(
|
||||
SRCS "host_test_main.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES libsrtp
|
||||
)
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Host (IDF Linux target) smoke + crypto-roundtrip test for libsrtp.
|
||||
*
|
||||
* - srtp_init() / srtp_shutdown()
|
||||
* - srtp_create() with AES-GCM-128 policy
|
||||
* - srtp_protect() + srtp_unprotect() roundtrip; assert plaintext is recovered
|
||||
*
|
||||
* Deeper coverage lives in libsrtp's own test/srtp_driver.c; we exercise
|
||||
* the protect/unprotect happy path here as a sanity-check that the
|
||||
* ESP-IDF Linux-target build produces a working library.
|
||||
*
|
||||
* Both CHECK() (libsrtp return-status) and EXPECT() (boolean condition)
|
||||
* bail out immediately on failure — continuing past a context/init failure
|
||||
* would either mask the original error or crash on uninitialised state.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "srtp2/srtp.h"
|
||||
|
||||
#define CHECK(_e) \
|
||||
do { \
|
||||
srtp_err_status_t _s = (_e); \
|
||||
if (_s != srtp_err_status_ok) { \
|
||||
fprintf(stderr, "FAIL: %s -> %d\n", #_e, (int)_s); \
|
||||
exit(1); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define EXPECT(_cond, _fmt, ...) \
|
||||
do { \
|
||||
if (!(_cond)) { \
|
||||
fprintf(stderr, "FAIL: " _fmt "\n", ##__VA_ARGS__); \
|
||||
exit(1); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int run_smoke(void)
|
||||
{
|
||||
printf("libsrtp host_test: libsrtp version %s\n", srtp_get_version_string());
|
||||
|
||||
CHECK(srtp_init());
|
||||
|
||||
/* Build a sender + receiver context against the same AES-GCM-128 policy. */
|
||||
static const uint8_t key[SRTP_AES_GCM_128_KEY_LEN_WSALT] = { 0 };
|
||||
|
||||
srtp_policy_t policy_tx = { 0 };
|
||||
srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy_tx.rtp);
|
||||
srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy_tx.rtcp);
|
||||
policy_tx.ssrc.type = ssrc_any_outbound;
|
||||
policy_tx.key = (uint8_t *)key;
|
||||
policy_tx.window_size = 128;
|
||||
|
||||
srtp_policy_t policy_rx = policy_tx;
|
||||
policy_rx.ssrc.type = ssrc_any_inbound;
|
||||
|
||||
srtp_t sender = NULL;
|
||||
srtp_t receiver = NULL;
|
||||
CHECK(srtp_create(&sender, &policy_tx));
|
||||
CHECK(srtp_create(&receiver, &policy_rx));
|
||||
|
||||
/* Minimal RTP-shaped buffer:
|
||||
* 12B header (V=2, PT=0, seq=1, ts=0, ssrc=0xCAFEBABE)
|
||||
* payload "hello srtp"
|
||||
*/
|
||||
uint8_t pkt[12 + 10 + SRTP_MAX_TRAILER_LEN] = {
|
||||
0x80, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0xCA, 0xFE, 0xBA, 0xBE,
|
||||
'h', 'e', 'l', 'l', 'o', ' ', 's', 'r', 't', 'p',
|
||||
};
|
||||
int protected_len = 12 + 10;
|
||||
|
||||
CHECK(srtp_protect(sender, pkt, &protected_len));
|
||||
EXPECT(protected_len > 12 + 10,
|
||||
"protect did not expand the packet (got len=%d)", protected_len);
|
||||
|
||||
int unprotected_len = protected_len;
|
||||
CHECK(srtp_unprotect(receiver, pkt, &unprotected_len));
|
||||
EXPECT(unprotected_len == 12 + 10,
|
||||
"unprotect returned wrong len (got %d, want %d)", unprotected_len, 12 + 10);
|
||||
EXPECT(memcmp(pkt + 12, "hello srtp", 10) == 0,
|
||||
"recovered payload mismatch");
|
||||
|
||||
srtp_dealloc(sender);
|
||||
srtp_dealloc(receiver);
|
||||
CHECK(srtp_shutdown());
|
||||
|
||||
printf("libsrtp host_test: PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
exit(run_smoke());
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
libsrtp:
|
||||
version: "*"
|
||||
override_path: "../.."
|
||||
@@ -0,0 +1,18 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
import glob
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
from pytest_embedded_idf.utils import idf_parametrize
|
||||
|
||||
|
||||
@pytest.mark.host_test
|
||||
@pytest.mark.skipif(
|
||||
not bool(glob.glob(f'{Path(__file__).parent.absolute()}/build*/')),
|
||||
reason='Skip the idf version that not build',
|
||||
)
|
||||
@idf_parametrize('target', ['linux'], indirect=['target'])
|
||||
def test_libsrtp_linux(dut: Dut) -> None:
|
||||
dut.expect_exact('libsrtp host_test: PASS', timeout=30)
|
||||
@@ -0,0 +1,2 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
CONFIG_COMPILER_OPTIMIZATION_DEBUG=y
|
||||
@@ -0,0 +1,35 @@
|
||||
version: "2.8.0"
|
||||
description: "libsrtp (Cisco) wrapper for ESP-IDF — mbedTLS crypto backend with AES-GCM + AES-CM + HMAC-SHA1. SRTP/SRTCP packet protection for WebRTC and other RTP-based protocols."
|
||||
url: https://github.com/espressif/esp-protocols/tree/master/components/libsrtp
|
||||
repository: https://github.com/espressif/esp-protocols.git
|
||||
issues: https://github.com/espressif/esp-protocols/issues
|
||||
documentation: https://github.com/espressif/esp-protocols/blob/master/components/libsrtp/README.md
|
||||
license: "Apache-2.0 AND BSD-3-Clause"
|
||||
tags:
|
||||
- libsrtp
|
||||
- srtp
|
||||
- webrtc
|
||||
- mbedtls
|
||||
dependencies:
|
||||
# Upper bound is intentional. libsrtp v2.x's mbedTLS adapters use the
|
||||
# legacy <mbedtls/aes.h> / <mbedtls/gcm.h> headers; ESP-IDF v6 ships
|
||||
# mbedTLS 4 which reorganised those into the TF-PSA-Crypto split.
|
||||
# Bump the bound once the component tracks a libsrtp release that
|
||||
# speaks mbedTLS 4 (see cisco/libsrtp#812 for context).
|
||||
idf: ">=5.4,<6"
|
||||
|
||||
# SBOM manifest for the wrapped upstream — see sbom_libsrtp.yml.
|
||||
sbom:
|
||||
manifests:
|
||||
- path: sbom_libsrtp.yml
|
||||
dest: libsrtp
|
||||
|
||||
# Files excluded from the registry tarball (saves bytes, avoids confusion).
|
||||
files:
|
||||
exclude:
|
||||
- "libsrtp/test/**" # upstream tests are linked at host_test/ build time
|
||||
- "libsrtp/doc/**"
|
||||
- "libsrtp/**/.git*"
|
||||
- "host_test/build*"
|
||||
- "test_apps/build*"
|
||||
- "examples/*/build*"
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Thin shim that re-exposes upstream cisco/libsrtp's public API header
|
||||
* under the `srtp2/` install-path namespace, so downstream consumers
|
||||
* can use the canonical `#include <srtp2/srtp.h>` form without us
|
||||
* vendoring a copy of the upstream header in this repo.
|
||||
*/
|
||||
#include <srtp.h>
|
||||
Submodule
+1
Submodule components/libsrtp/libsrtp added at 24b3bf8f19
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* ESP-IDF build configuration for libsrtp. Define values are chosen to
|
||||
* match the ESP-IDF/newlib environment; format follows libsrtp's
|
||||
* upstream config.h.in template (BSD-3-Clause).
|
||||
*/
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h> // For PRIx64 / PRIu64 macros (needed on Apple clang / Linux target)
|
||||
#include <stddef.h> // For size_t definition
|
||||
|
||||
/*
|
||||
* CPU architecture hint. libsrtp uses this only to select a fast endian-flip
|
||||
* path in a few places; the C fallback is correct on all targets. ESP-IDF's
|
||||
* supported targets are Xtensa (esp32 / s2 / s3) and RISC-V (c3 / c5 / c6 /
|
||||
* p4 / h2), so CPU_CISC would be wrong here. Set CPU_RISC for the embedded
|
||||
* targets and leave it unset (= C fallback) on the IDF Linux host target.
|
||||
*/
|
||||
#if defined(__XTENSA__) || defined(__riscv)
|
||||
#define CPU_RISC 1
|
||||
#endif
|
||||
|
||||
/* Report errors to stdout. */
|
||||
#define ERR_REPORTING_STDOUT 1
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#define HAVE_NETINET_IN_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#define HAVE_SYS_SOCKET_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you want to use external crypto. */
|
||||
#define SRTP_CRYPTO_MBEDTLS 1
|
||||
|
||||
/* Define package info */
|
||||
#define PACKAGE_NAME "libsrtp"
|
||||
#define PACKAGE_VERSION "2.8.0"
|
||||
#define PACKAGE_STRING PACKAGE_NAME " " PACKAGE_VERSION
|
||||
|
||||
/* The size of `unsigned long', as computed by sizeof. */
|
||||
#define SIZEOF_UNSIGNED_LONG 4
|
||||
|
||||
/* The size of `unsigned long long', as computed by sizeof. */
|
||||
#define SIZEOF_UNSIGNED_LONG_LONG 8
|
||||
|
||||
/* Force SRTP to use system types */
|
||||
#define HAVE_STDINT_H 1
|
||||
#define HAVE_INTTYPES_H 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_UINT64_T 1
|
||||
#define HAVE_UINT32_T 1
|
||||
#define HAVE_UINT16_T 1
|
||||
#define HAVE_UINT8_T 1
|
||||
#define HAVE_INT64_T 1
|
||||
#define HAVE_INT32_T 1
|
||||
#define HAVE_INT16_T 1
|
||||
#define HAVE_INT8_T 1
|
||||
|
||||
/* Prevent SRTP from redefining types */
|
||||
#define INTEGERS_H
|
||||
|
||||
/* Prevent srtp_ssrc_t redefinition */
|
||||
#ifdef __XTENSA__
|
||||
#define SRTP_KERNEL_COMPAT
|
||||
#endif
|
||||
|
||||
/* Prevent in_addr_t redefinition */
|
||||
#ifndef _LWIP_INET_H
|
||||
typedef uint32_t in_addr_t;
|
||||
#endif
|
||||
|
||||
#define GCM 1
|
||||
#define MBEDTLS 1
|
||||
#define ERR_REPORTING_STDOUT 1
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
@@ -0,0 +1,561 @@
|
||||
/*
|
||||
* 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 "alloc.h"
|
||||
|
||||
#include "crypto_kernel.h"
|
||||
#include "cipher_types.h"
|
||||
|
||||
/* the debug module for the crypto_kernel */
|
||||
|
||||
srtp_debug_module_t srtp_mod_crypto_kernel = {
|
||||
0, /* debugging is off by default */
|
||||
"crypto kernel" /* printable name for module */
|
||||
};
|
||||
|
||||
/* 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
|
||||
#if 0
|
||||
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_192,
|
||||
SRTP_AES_ICM_192);
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
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 authentication 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,
|
||||
int 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, 0);
|
||||
}
|
||||
|
||||
srtp_err_status_t srtp_replace_cipher_type(const srtp_cipher_type_t *new_ct,
|
||||
srtp_cipher_type_id_t id)
|
||||
{
|
||||
return srtp_crypto_kernel_do_load_cipher_type(new_ct, id, 1);
|
||||
}
|
||||
|
||||
srtp_err_status_t srtp_crypto_kernel_do_load_auth_type(
|
||||
const srtp_auth_type_t *new_at,
|
||||
srtp_auth_type_id_t id,
|
||||
int replace)
|
||||
{
|
||||
srtp_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, 0);
|
||||
}
|
||||
|
||||
srtp_err_status_t srtp_replace_auth_type(const srtp_auth_type_t *new_at,
|
||||
srtp_auth_type_id_t id)
|
||||
{
|
||||
return srtp_crypto_kernel_do_load_auth_type(new_at, id, 1);
|
||||
}
|
||||
|
||||
const srtp_cipher_type_t *srtp_crypto_kernel_get_cipher_type(
|
||||
srtp_cipher_type_id_t id)
|
||||
{
|
||||
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,
|
||||
int key_len,
|
||||
int 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,
|
||||
int key_len,
|
||||
int 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, int 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;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
name: 'libsrtp'
|
||||
supplier: 'Organization: Espressif Systems (Shanghai) CO LTD'
|
||||
originator: 'Organization: Espressif Systems (Shanghai) CO LTD'
|
||||
description: ESP-IDF wrapper for libsrtp (Cisco) using mbedtls crypto backend with AES-GCM. Used for SRTP/SRTCP packet protection in WebRTC and other RTP-based protocols.
|
||||
virtpackages:
|
||||
- sbom_libsrtp.yml
|
||||
@@ -0,0 +1,10 @@
|
||||
name: libsrtp
|
||||
version: 2.8.0
|
||||
cpe: cpe:2.3:a:cisco:libsrtp:{}:*:*:*:*:*:*:*
|
||||
supplier: 'Organization: Cisco Systems, Inc. <https://github.com/cisco/libsrtp>'
|
||||
description: Library for the Secure Real-time Transport Protocol (SRTP, RFC 3711) and Secure RTCP (SRTCP). Submodule pinned at upstream release tag v2.8.0 (commit 24b3bf8). One small ESP-IDF specific delta lives in port/crypto_kernel.c — it opts out of the AES-ICM-192 cipher registration when GCM is enabled (saves binary size; AES-CM-128 and AES-GCM cover all WebRTC SRTP suites).
|
||||
url: https://github.com/cisco/libsrtp
|
||||
hash: 24b3bf8f19b6f5ab4cd2bcceb4f4064efca86fd5
|
||||
cve-exclude-list:
|
||||
- cve: CVE-2023-31222
|
||||
reason: Resolved in 2.6.0; current pin (v2.8.0) is well past.
|
||||
@@ -0,0 +1,11 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# Pull the parent component via override_path so the test exercises
|
||||
# THIS working tree, not whatever's in the registry / managed_components.
|
||||
set(EXTRA_COMPONENT_DIRS "..")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(test_app_libsrtp)
|
||||
@@ -0,0 +1,8 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
idf_component_register(
|
||||
SRCS "test_libsrtp_main.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES unity libsrtp
|
||||
)
|
||||
@@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
libsrtp:
|
||||
version: "*"
|
||||
override_path: "../.."
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Embedded smoke test for libsrtp. Validates that the component
|
||||
* links cleanly on the chosen target and exposes the libsrtp public
|
||||
* API. Deeper coverage lives in host_test/ (runs against the IDF
|
||||
* Linux target and reuses upstream libsrtp's own test suite).
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
#include "srtp2/srtp.h"
|
||||
|
||||
TEST_CASE("srtp_init then srtp_shutdown succeed", "[srtp2]")
|
||||
{
|
||||
TEST_ASSERT_EQUAL(srtp_err_status_ok, srtp_init());
|
||||
TEST_ASSERT_EQUAL(srtp_err_status_ok, srtp_shutdown());
|
||||
}
|
||||
|
||||
TEST_CASE("srtp_get_version_string returns non-empty", "[srtp2]")
|
||||
{
|
||||
const char *v = srtp_get_version_string();
|
||||
TEST_ASSERT_NOT_NULL(v);
|
||||
TEST_ASSERT_GREATER_THAN(0, strlen(v));
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
unity_run_all_tests();
|
||||
UNITY_END();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize("target", ["esp32", "esp32c3"], indirect=True)
|
||||
def test_libsrtp_smoke(dut):
|
||||
dut.expect_unity_test_output(timeout=30)
|
||||
@@ -0,0 +1,3 @@
|
||||
# Speed up CI run + small binary
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_FREERTOS_UNICORE=y
|
||||
Reference in New Issue
Block a user