From 480d6837589c696a6983ac3fe224220f348ad9ef Mon Sep 17 00:00:00 2001 From: Dmitry Kolbik Date: Mon, 17 Feb 2025 06:08:38 +0100 Subject: [PATCH 1/8] Add TLS/SSL backend: Mbed TLS (#4295) --- aconfigure | 114 +++- aconfigure.ac | 46 +- pjlib/build/Makefile | 2 +- pjlib/include/pj/config.h | 3 + pjlib/src/pj/ssl_sock_mbedtls.c | 909 ++++++++++++++++++++++++++++++++ pjlib/src/pjlib-test/ssl_sock.c | 4 + 6 files changed, 1073 insertions(+), 5 deletions(-) create mode 100644 pjlib/src/pj/ssl_sock_mbedtls.c diff --git a/aconfigure b/aconfigure index cf7ece6db5..723f048e6d 100755 --- a/aconfigure +++ b/aconfigure @@ -668,6 +668,8 @@ opencore_amrnb_present opencore_amrnb_h_present ac_no_opencore_amrwb ac_no_opencore_amrnb +libmbedtls_present +mbedtls_h_present libgnutls_present gnutls_h_present libcrypto_present @@ -867,6 +869,7 @@ with_ipp_arch enable_android_mediacodec with_ssl with_gnutls +with_mbedtls enable_darwin_ssl enable_ssl with_opencore_amrnb @@ -1625,6 +1628,7 @@ Optional Packages: GnuTLS. To skip OpenSSL finding, use --with-gnutls option instead. --with-gnutls=DIR Specify alternate GnuTLS prefix + --with-mbedtls=DIR Specify alternate MbedTLS prefix --with-opencore-amrnb=DIR This option is obsolete and replaced by --with-opencore-amr=DIR @@ -9683,7 +9687,19 @@ esac fi -if test "x$ac_cross_compile" != "x" -a "x$with_ssl" = "xno" -a "x$with_gnutls" = "xno"; then + +# Check whether --with-mbedtls was given. +if test ${with_mbedtls+y} +then : + withval=$with_mbedtls; +else case e in #( + e) with_mbedtls=no + ;; +esac +fi + + +if test "x$ac_cross_compile" != "x" -a "x$with_ssl" = "xno" -a "x$with_gnutls" = "xno" -a "x$with_mbedtls" = "xno"; then enable_ssl=no fi @@ -9775,7 +9791,7 @@ else case e in #( printf "%s\n" "Using SSL prefix... $with_ssl" >&6; } fi - if test "x$with_gnutls" = "xno"; then + if test "x$with_gnutls" = "xno" -a "x$with_mbedtls" = "xno"; then # We still need to check for OpenSSL installations even if # we find Darwin SSL above since DTLS requires OpenSSL. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: checking for OpenSSL installations.." >&5 @@ -10139,6 +10155,100 @@ printf "%s\n" "** No GnuTLS libraries found, disabling SSL support **" >&6; } fi + if test "x$ac_ssl_backend" = "x"; then + if test "x$with_mbedtls" != "xno" -a "x$with_mbedtls" != "x"; then + CFLAGS="$CFLAGS -I$with_mbedtls/include" + LDFLAGS="$LDFLAGS -L$with_mbedtls/lib" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using MbedTLS prefix... $with_mbedtls" >&5 +printf "%s\n" "Using MbedTLS prefix... $with_mbedtls" >&6; } + fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: checking for MbedTLS installations.." >&5 +printf "%s\n" "checking for MbedTLS installations.." >&6; } + + + ac_fn_c_check_header_compile "$LINENO" "mbedtls/version.h" "ac_cv_header_mbedtls_version_h" "$ac_includes_default" +if test "x$ac_cv_header_mbedtls_version_h" = xyes +then : + mbedtls_h_present=1 +fi + + + if test "$PKG_CONFIG" != "none"; then + if $PKG_CONFIG --exists mbedtls mbedcrypto mbedx509; then + LIBS="$LIBS `$PKG_CONFIG --libs mbedtls mbedcrypto mbedx509`" + libmbedtls_present=1 + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mbedtls_version_get_number in -lmbedtls" >&5 +printf %s "checking for mbedtls_version_get_number in -lmbedtls... " >&6; } +if test ${ac_cv_lib_mbedtls_mbedtls_version_get_number+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) ac_check_lib_save_LIBS=$LIBS +LIBS="-lmbedtls $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. + The 'extern "C"' is for builds by C++ compilers; + although this is not generally supported in C code supporting it here + has little cost and some practical benefit (sr 110532). */ +#ifdef __cplusplus +extern "C" +#endif +char mbedtls_version_get_number (void); +int +main (void) +{ +return mbedtls_version_get_number (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_mbedtls_mbedtls_version_get_number=yes +else case e in #( + e) ac_cv_lib_mbedtls_mbedtls_version_get_number=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mbedtls_mbedtls_version_get_number" >&5 +printf "%s\n" "$ac_cv_lib_mbedtls_mbedtls_version_get_number" >&6; } +if test "x$ac_cv_lib_mbedtls_mbedtls_version_get_number" = xyes +then : + + libmbedtls_present=1 && LIBS="$LIBS -lmbedtls" +fi + + fi + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: *** Warning: neither pkg-config nor python is available, disabling mbedtls. ***" >&5 +printf "%s\n" "*** Warning: neither pkg-config nor python is available, disabling mbedtls. ***" >&6; } + fi + + if test "x$mbedtls_h_present" = "x1" -a "x$libmbedtls_present" = "x1"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: MbedTLS library found, SSL support enabled" >&5 +printf "%s\n" "MbedTLS library found, SSL support enabled" >&6; } + printf "%s\n" "#define PJ_HAS_SSL_SOCK 1" >>confdefs.h + + printf "%s\n" "#define PJ_SSL_SOCK_IMP PJ_SSL_SOCK_IMP_MBEDTLS" >>confdefs.h + + ac_ssl_backend="mbedtls" + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ** No MbedTLS libraries found, disabling SSL support **" >&5 +printf "%s\n" "** No MbedTLS libraries found, disabling SSL support **" >&6; } + fi + + fi + ;; esac fi diff --git a/aconfigure.ac b/aconfigure.ac index 7d304595e2..fdecf082bf 100644 --- a/aconfigure.ac +++ b/aconfigure.ac @@ -2106,8 +2106,15 @@ AC_ARG_WITH(gnutls, [with_gnutls=no] ) +dnl # MbedTLS alt prefix +AC_ARG_WITH(mbedtls, + AS_HELP_STRING([--with-mbedtls=DIR], [Specify alternate MbedTLS prefix]), + [], + [with_mbedtls=no] +) + dnl # Do not use default SSL installation if we are cross-compiling -if test "x$ac_cross_compile" != "x" -a "x$with_ssl" = "xno" -a "x$with_gnutls" = "xno"; then +if test "x$ac_cross_compile" != "x" -a "x$with_ssl" = "xno" -a "x$with_gnutls" = "xno" -a "x$with_mbedtls" = "xno"; then enable_ssl=no fi @@ -2174,7 +2181,7 @@ AC_ARG_ENABLE(ssl, AC_MSG_RESULT([Using SSL prefix... $with_ssl]) fi - if test "x$with_gnutls" = "xno"; then + if test "x$with_gnutls" = "xno" -a "x$with_mbedtls" = "xno"; then # We still need to check for OpenSSL installations even if # we find Darwin SSL above since DTLS requires OpenSSL. AC_MSG_RESULT([checking for OpenSSL installations..]) @@ -2264,6 +2271,41 @@ AC_ARG_ENABLE(ssl, fi fi + + if test "x$ac_ssl_backend" = "x"; then + if test "x$with_mbedtls" != "xno" -a "x$with_mbedtls" != "x"; then + CFLAGS="$CFLAGS -I$with_mbedtls/include" + LDFLAGS="$LDFLAGS -L$with_mbedtls/lib" + AC_MSG_RESULT([Using MbedTLS prefix... $with_mbedtls]) + fi + + AC_MSG_RESULT([checking for MbedTLS installations..]) + AC_SUBST(mbedtls_h_present) + AC_SUBST(libmbedtls_present) + AC_CHECK_HEADER(mbedtls/version.h, [mbedtls_h_present=1]) + + if test "$PKG_CONFIG" != "none"; then + if $PKG_CONFIG --exists mbedtls mbedcrypto mbedx509; then + LIBS="$LIBS `$PKG_CONFIG --libs mbedtls mbedcrypto mbedx509`" + libmbedtls_present=1 + else + AC_CHECK_LIB(mbedtls, mbedtls_version_get_number, [ + libmbedtls_present=1 && LIBS="$LIBS -lmbedtls"]) + fi + else + AC_MSG_RESULT([*** Warning: neither pkg-config nor python is available, disabling mbedtls. ***]) + fi + + if test "x$mbedtls_h_present" = "x1" -a "x$libmbedtls_present" = "x1"; then + AC_MSG_RESULT([MbedTLS library found, SSL support enabled]) + AC_DEFINE(PJ_HAS_SSL_SOCK, 1) + AC_DEFINE(PJ_SSL_SOCK_IMP, PJ_SSL_SOCK_IMP_MBEDTLS) + ac_ssl_backend="mbedtls" + else + AC_MSG_RESULT([** No MbedTLS libraries found, disabling SSL support **]) + fi + + fi ] ) diff --git a/pjlib/build/Makefile b/pjlib/build/Makefile index caf01121d6..3d4bd7fd7e 100644 --- a/pjlib/build/Makefile +++ b/pjlib/build/Makefile @@ -36,7 +36,7 @@ export PJLIB_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \ os_time_common.o os_info.o pool.o pool_buf.o pool_caching.o pool_dbg.o \ rand.o rbtree.o sock_common.o sock_qos_common.o \ ssl_sock_common.o ssl_sock_ossl.o ssl_sock_gtls.o ssl_sock_dump.o \ - ssl_sock_darwin.o string.o timer.o types.o unittest.o + ssl_sock_darwin.o ssl_sock_mbedtls.o string.o timer.o types.o unittest.o export PJLIB_CFLAGS += $(_CFLAGS) export PJLIB_CXXFLAGS += $(_CXXFLAGS) export PJLIB_LDFLAGS += $(_LDFLAGS) diff --git a/pjlib/include/pj/config.h b/pjlib/include/pj/config.h index f4809ce788..d98254eb5e 100644 --- a/pjlib/include/pj/config.h +++ b/pjlib/include/pj/config.h @@ -1117,6 +1117,9 @@ /** Using Windows's Schannel */ #define PJ_SSL_SOCK_IMP_SCHANNEL 5 +/** Using Mbed TLS */ +#define PJ_SSL_SOCK_IMP_MBEDTLS 6 + /** * Select which SSL socket implementation to use. Currently pjlib supports * PJ_SSL_SOCK_IMP_OPENSSL, which uses OpenSSL, and PJ_SSL_SOCK_IMP_GNUTLS, diff --git a/pjlib/src/pj/ssl_sock_mbedtls.c b/pjlib/src/pj/ssl_sock_mbedtls.c new file mode 100644 index 0000000000..8b4d4388f1 --- /dev/null +++ b/pjlib/src/pj/ssl_sock_mbedtls.c @@ -0,0 +1,909 @@ +/* + * Copyright (C) 2025 Teluu Inc. (http://www.teluu.com) + * Copyright (c) 2025 Arlo Technologies, Inc. (https://www.arlo.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Only build when PJ_HAS_SSL_SOCK is enabled and when the backend is + * MbedTLS. + */ +#if defined(PJ_HAS_SSL_SOCK) && PJ_HAS_SSL_SOCK != 0 && \ + (PJ_SSL_SOCK_IMP == PJ_SSL_SOCK_IMP_MBEDTLS) + +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/debug.h" +#include "mbedtls/entropy.h" +#include "mbedtls/error.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform.h" +#include "mbedtls/pk.h" +#include "mbedtls/ssl.h" +#include "mbedtls/version.h" + +#ifdef MBEDTLS_DEBUG_C +#define MBEDTLS_DEBUG_VERBOSE 1 +#endif + +#define SSL_SOCK_IMP_USE_CIRC_BUF + +#include "ssl_sock_imp_common.h" + +#define THIS_FILE "ssl_sock_mbedtls.c" + +/* + * Secure socket structure definition. + */ +typedef struct mbedtls_sock_t { + pj_ssl_sock_t base; + + mbedtls_ssl_context ssl_ctx; + mbedtls_ssl_config ssl_config; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_x509_crt cacert; + mbedtls_x509_crt cert; + mbedtls_pk_context pk_ctx; +} mbedtls_sock_t; + +#include "ssl_sock_imp_common.c" + +/* + ******************************************************************* + * Static/internal functions. + ******************************************************************* + */ + +/* MbedTLS way of reporting internal operations. */ +static void mbedtls_print_logs(void *ctx, int level, const char *file, + int line, const char *str) +{ + const char* last_slash; + const char* file_name; + + PJ_UNUSED_ARG(ctx); + PJ_UNUSED_ARG(level); + + last_slash = strrchr(file, '/'); + file_name = last_slash ? last_slash + 1 : file; + + PJ_LOG(3, (THIS_FILE, "%s:%d: %s", file_name, line, str)); +} + +/* Convert from MbedTLS error to pj_status_t. */ +static pj_status_t ssl_status_from_err(pj_ssl_sock_t *ssock, int err) +{ + pj_status_t status; + + PJ_UNUSED_ARG(ssock); + + switch (err) { + case 0: + status = PJ_SUCCESS; + break; + case MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL: + case MBEDTLS_ERR_SSL_ALLOC_FAILED: + status = PJ_ENOMEM; + break; + case MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE: + status = PJ_ETOOBIG; + break; + case MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE: + status = PJ_ENOTFOUND; + break; + case MBEDTLS_ERR_SSL_TIMEOUT: + status = PJ_ETIMEDOUT; + break; + case MBEDTLS_ERR_SSL_INTERNAL_ERROR: + case MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY: + status = PJ_EBUG; + break; + case MBEDTLS_ERR_SSL_WANT_READ: + case MBEDTLS_ERR_SSL_WANT_WRITE: + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS: + case MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA: + case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET: + status = PJ_EPENDING; + break; + + case MBEDTLS_ERR_SSL_UNEXPECTED_RECORD: + case MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER: + case MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION: + case MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE: + status = PJ_EINVAL; + break; + default: + status = PJ_EUNKNOWN; + break; + } + + return status; +} + +static int ssl_data_push(void *ctx, const unsigned char *buf, size_t len) +{ + pj_ssl_sock_t *ssock = (pj_ssl_sock_t *)ctx; + + pj_lock_acquire(ssock->circ_buf_output_mutex); + if (circ_write(&ssock->circ_buf_output, buf, len) != PJ_SUCCESS) { + pj_lock_release(ssock->circ_buf_output_mutex); + + return MBEDTLS_ERR_SSL_WANT_WRITE; + } + + pj_lock_release(ssock->circ_buf_output_mutex); + + return len; +} + +static int ssl_data_pull(void *ctx, unsigned char *buf, size_t len) +{ + pj_ssl_sock_t *ssock = (pj_ssl_sock_t *)ctx; + pj_size_t circ_buf_size; + pj_size_t read_size; + + pj_lock_acquire(ssock->circ_buf_input_mutex); + + if (circ_empty(&ssock->circ_buf_input)) { + pj_lock_release(ssock->circ_buf_input_mutex); + + return MBEDTLS_ERR_SSL_WANT_READ; + } + + circ_buf_size = circ_size(&ssock->circ_buf_input); + read_size = PJ_MIN(circ_buf_size, len); + + circ_read(&ssock->circ_buf_input, buf, read_size); + pj_lock_release(ssock->circ_buf_input_mutex); + + return read_size; +} + +/* Get Common Name field string from a general name string */ +static void cert_get_cn(const pj_str_t *gen_name, pj_str_t *cn) +{ + pj_str_t CN_sign = {"CN=", 3}; + char *p, *q; + + pj_bzero(cn, sizeof(cn)); + + p = pj_strstr(gen_name, &CN_sign); + if (!p) + return; + + p += 3; /* shift pointer to value part */ + pj_strset(cn, p, gen_name->slen - (p - gen_name->ptr)); + q = pj_strchr(cn, ','); + if (q) + cn->slen = q - p; +} + +static void cert_get_time(pj_time_val *tv, + const mbedtls_x509_time *time, + pj_bool_t *gmt) +{ + pj_parsed_time pt; + + pt.day = time->day; + pt.mon = time->mon - 1; + pt.year = time->year; + + pt.sec = time->sec; + pt.min = time->min; + pt.hour = time->hour; + + pt.msec = 0; + + // Assume MbedTLS always use GMT + *gmt = PJ_TRUE; + + pj_time_encode(&pt, tv); +} + +static void cert_get_alt_name(const mbedtls_x509_crt *crt, + pj_pool_t *pool, + pj_ssl_cert_info *ci) +{ + const mbedtls_x509_sequence *cur; + size_t cnt_alt_name; + int ret; + + int is_alt_name = mbedtls_x509_crt_has_ext_type( + crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME); + if (!is_alt_name) + return; + + cnt_alt_name = 0; + cur = &crt->subject_alt_names; + while (cur != NULL) { + cur = cur->next; + cnt_alt_name++; + } + + ci->subj_alt_name.entry = pj_pool_calloc(pool, cnt_alt_name, + sizeof(*ci->subj_alt_name.entry)); + if (!ci->subj_alt_name.entry) { + PJ_LOG(2, (THIS_FILE, "Failed to allocate memory for SubjectAltName")); + return; + } + + ci->subj_alt_name.cnt = 0; + cur = &crt->subject_alt_names; + + while (cur != NULL) { + mbedtls_x509_subject_alternative_name san; + pj_ssl_cert_name_type type; + size_t len; + + memset(&san, 0, sizeof(san)); + ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san); + if (ret != 0) { + cur = cur->next; + continue; + } + + len = san.san.unstructured_name.len; + switch (san.type) { + case MBEDTLS_X509_SAN_RFC822_NAME: + type = PJ_SSL_CERT_NAME_RFC822; + break; + case MBEDTLS_X509_SAN_DNS_NAME: + type = PJ_SSL_CERT_NAME_DNS; + break; + case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: + type = PJ_SSL_CERT_NAME_URI; + break; + case MBEDTLS_X509_SAN_IP_ADDRESS: + type = PJ_SSL_CERT_NAME_IP; + break; + default: + type = PJ_SSL_CERT_NAME_UNKNOWN; + break; + } + + if (len && type != PJ_SSL_CERT_NAME_UNKNOWN) { + ci->subj_alt_name.entry[ci->subj_alt_name.cnt].type = type; + if (type == PJ_SSL_CERT_NAME_IP) { + char ip_buf[PJ_INET6_ADDRSTRLEN]; + int af = pj_AF_INET(); + if (len == sizeof(pj_in6_addr)) + af = pj_AF_INET6(); + pj_inet_ntop2(af, san.san.unstructured_name.p, + ip_buf, sizeof(ip_buf)); + pj_strdup2(pool, + &ci->subj_alt_name.entry[ci->subj_alt_name.cnt].name, + ip_buf); + } else { + const pj_str_t str = {(char *)san.san.unstructured_name.p, len}; + pj_strdup(pool, + &ci->subj_alt_name.entry[ci->subj_alt_name.cnt].name, + &str); + } + ci->subj_alt_name.cnt++; + } + + /* So far memory is freed only in the case of directoryName + * parsing succeeding, as mbedtls_x509_get_name allocates memory. + */ + mbedtls_x509_free_subject_alt_name(&san); + cur = cur->next; + } +} + +static void update_cert_info(const mbedtls_x509_crt *crt, + pj_pool_t *pool, pj_ssl_cert_info *ci) +{ + int ret; + char buf[1024]; + size_t bufsize = sizeof(buf); + + pj_bzero(ci, sizeof(pj_ssl_cert_info)); + + ci->version = crt->version; + + /* Serial number */ + pj_memcpy(ci->serial_no, crt->serial.p, sizeof(ci->serial_no)); + + /* Issuer */ + ret = mbedtls_x509_dn_gets(buf, bufsize, &crt->issuer); + if (ret < 0) { + PJ_LOG(2, (THIS_FILE, "Error parsing cert issuer")); + return; + } + pj_strdup2(pool, &ci->issuer.info, buf); + cert_get_cn(&ci->issuer.info, &ci->issuer.cn); + + /* Subject */ + ret = mbedtls_x509_dn_gets(buf, bufsize, &crt->subject); + if (ret < 0) { + PJ_LOG(2, (THIS_FILE, "Error parsing cert subject")); + return; + } + pj_strdup2(pool, &ci->subject.info, buf); + cert_get_cn(&ci->subject.info, &ci->subject.cn); + + /* Validity period */ + cert_get_time(&ci->validity.start, &crt->valid_from, &ci->validity.gmt); + cert_get_time(&ci->validity.end, &crt->valid_to, &ci->validity.gmt); + + /* Subject Alternative Name extension */ + cert_get_alt_name(crt, pool, ci); +} + +static pj_status_t set_ssl_protocol(pj_ssl_sock_t *ssock) +{ + mbedtls_sock_t *mssock = (mbedtls_sock_t *)ssock; + mbedtls_ssl_protocol_version max_proto; + mbedtls_ssl_protocol_version min_proto; + + if (ssock->param.proto == PJ_SSL_SOCK_PROTO_DEFAULT) { + ssock->param.proto = PJ_SSL_SOCK_PROTO_TLS1_2 | + PJ_SSL_SOCK_PROTO_TLS1_3; + } + + if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_3) { + max_proto = MBEDTLS_SSL_VERSION_TLS1_3; + } else if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_2) { + max_proto = MBEDTLS_SSL_VERSION_TLS1_2; + } else { + PJ_LOG(1, (THIS_FILE, "Unsupported TLS protocol")); + return PJ_EINVAL; + } + + if (ssock->param.proto & PJ_SSL_SOCK_PROTO_TLS1_2) { + min_proto = MBEDTLS_SSL_VERSION_TLS1_2; + } else { + min_proto = MBEDTLS_SSL_VERSION_TLS1_3; + } + + mbedtls_ssl_conf_min_tls_version(&mssock->ssl_config, min_proto); + mbedtls_ssl_conf_max_tls_version(&mssock->ssl_config, max_proto); + + return PJ_SUCCESS; +} + +static int cert_verify_cb(void *data, mbedtls_x509_crt *crt, + int depth, uint32_t *flags) +{ + pj_ssl_sock_t *ssock = (pj_ssl_sock_t *)data; + const int cert_dump_log_level = 5; + + if (pj_log_get_level() >= cert_dump_log_level) { + char buf[1024]; + PJ_LOG(5, (THIS_FILE, "Certificate index in chain " + "- %d", depth)); + mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); + PJ_LOG(5, (THIS_FILE, "Certificate info:\n%s", buf)); + } + + /* Peer cert depth = 0 */ + if (depth > 0) + return 0; + + if (((*flags) & MBEDTLS_X509_BADCERT_EXPIRED) != 0) { + PJ_LOG(3, (THIS_FILE, "Server certificate has expired!")); + ssock->verify_status |= PJ_SSL_CERT_EVALIDITY_PERIOD; + } + + if (((*flags) & MBEDTLS_X509_BADCERT_REVOKED) != 0) { + PJ_LOG(3, (THIS_FILE, "Server certificate has been revoked!")); + ssock->verify_status |= PJ_SSL_CERT_EREVOKED; + } + + if (((*flags) & MBEDTLS_X509_BADCERT_CN_MISMATCH) != 0) { + PJ_LOG(3, (THIS_FILE, "CN mismatch!")); + ssock->verify_status |= PJ_SSL_CERT_EISSUER_MISMATCH; + } + + if (((*flags) & MBEDTLS_X509_BADCERT_NOT_TRUSTED) != 0) { + PJ_LOG(3, (THIS_FILE, "Self-signed or not signed by a trusted CA!")); + ssock->verify_status |= PJ_SSL_CERT_EUNTRUSTED; + } + + if (((*flags) & MBEDTLS_X509_BADCRL_NOT_TRUSTED) != 0) { + PJ_LOG(3, (THIS_FILE, "CRL not trusted!")); + ssock->verify_status |= PJ_SSL_CERT_EUNTRUSTED; + } + + if (((*flags) & MBEDTLS_X509_BADCRL_EXPIRED) != 0) { + PJ_LOG(3, (THIS_FILE, "CRL expired!")); + ssock->verify_status |= PJ_SSL_CERT_EVALIDITY_PERIOD; + } + + if (((*flags) & MBEDTLS_X509_BADCERT_OTHER) != 0) { + PJ_LOG(3, (THIS_FILE, "other (unknown) flags!")); + ssock->verify_status |= PJ_SSL_CERT_EUNKNOWN; + } + + if ((*flags) == 0) { + PJ_LOG(5, (THIS_FILE, "Certificate verified without error flags")); + } else { + update_cert_info(crt, ssock->pool, &ssock->remote_cert_info); + } + + return 0; +} + +static pj_status_t set_cert(pj_ssl_sock_t *ssock) +{ + mbedtls_sock_t *mssock = (mbedtls_sock_t *)ssock; + mbedtls_x509_crt *cacert_ = NULL; + int authmode = MBEDTLS_SSL_VERIFY_NONE; + int ret = 0; + pj_ssl_cert_t *cert = ssock->cert; + + if (cert == NULL) + goto on_config; + + if (cert->CA_buf.slen) { + ret = mbedtls_x509_crt_parse(&mssock->cacert, + (const unsigned char *)cert->CA_buf.ptr, + cert->CA_buf.slen); + if (ret != 0) { + PJ_LOG(1, (THIS_FILE, "Failed to CA mbedtls_x509_crt_parse, " + "ret = -0x%04X", -ret)); + goto on_error; + } + cacert_ = &mssock->cacert; + } + + if (cert->cert_buf.slen && cert->privkey_buf.slen) { + ret = mbedtls_x509_crt_parse(&mssock->cert, + (const unsigned char *)cert->cert_buf.ptr, + cert->cert_buf.slen); + if (ret != 0) { + PJ_LOG(1, (THIS_FILE, "Failed to mbedtls_x509_crt_parse, " + "ret = -0x%04X", -ret)); + goto on_error; + } + + ret = mbedtls_pk_parse_key(&mssock->pk_ctx, + (const unsigned char *)cert->privkey_buf.ptr, + cert->privkey_buf.slen, + (const unsigned char *)cert->privkey_pass.ptr, + cert->privkey_pass.slen, + mbedtls_ctr_drbg_random, &mssock->ctr_drbg); + if (ret != 0) { + PJ_LOG(1, (THIS_FILE, "Failed to mbedtls_pk_parse, " + "ret = -0x%04X", -ret)); + goto on_error; + } + + mbedtls_ssl_conf_own_cert(&mssock->ssl_config, + &mssock->cert, + &mssock->pk_ctx); + } + +#if defined(MBEDTLS_FS_IO) + if (cert->CA_file.slen) { + ret = mbedtls_x509_crt_parse_file(&mssock->cacert, cert->CA_file.ptr); + if (ret != 0) { + PJ_LOG(1, (THIS_FILE, "Failed to CA mbedtls_x509_crt_parse_file, " + "ret = -0x%04X", -ret)); + goto on_error; + } + cacert_ = &mssock->cacert; + } + + if (cert->CA_path.slen) { + ret = mbedtls_x509_crt_parse_path(&mssock->cacert, cert->CA_path.ptr); + if (ret != 0) { + PJ_LOG(1, (THIS_FILE, "Failed to CA mbedtls_x509_crt_parse_path, " + "ret = -0x%04X", -ret)); + goto on_error; + } + cacert_ = &mssock->cacert; + } + + if (cert->cert_file.slen && cert->privkey_file.slen) { + ret = mbedtls_x509_crt_parse_file(&mssock->cert, cert->cert_file.ptr); + if (ret != 0) { + PJ_LOG(1, (THIS_FILE, "Failed to mbedtls_x509_crt_parse_file, " + "ret = -0x%04X", -ret)); + goto on_error; + } + + ret = mbedtls_pk_parse_keyfile(&mssock->pk_ctx, + cert->privkey_file.ptr, + cert->privkey_pass.ptr, + mbedtls_ctr_drbg_random, + &mssock->ctr_drbg); + if (ret != 0) { + PJ_LOG(1, (THIS_FILE, "Failed to mbedtls_pk_parse_keyfile, " + "ret = -0x%04X", -ret)); + goto on_error; + } + + mbedtls_ssl_conf_own_cert(&mssock->ssl_config, + &mssock->cert, + &mssock->pk_ctx); + } +#endif + +on_config: + if (ssock->is_server) { + if (ssock->param.require_client_cert) { + authmode = MBEDTLS_SSL_VERIFY_REQUIRED; + } else { + authmode = MBEDTLS_SSL_VERIFY_OPTIONAL; + } + } else { + if (cacert_) + authmode = MBEDTLS_SSL_VERIFY_REQUIRED; + else + PJ_LOG(2, (THIS_FILE, "Peer validation is disabled")); + } + + mbedtls_ssl_conf_verify(&mssock->ssl_config, cert_verify_cb, ssock); + mbedtls_ssl_conf_ca_chain(&mssock->ssl_config, cacert_, NULL); + mbedtls_ssl_conf_authmode(&mssock->ssl_config, authmode); + +on_error: + return ssl_status_from_err(ssock, ret); +} + +static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock) +{ + mbedtls_sock_t *mssock = (mbedtls_sock_t *)ssock; + + /* mbedtls_ssl_conf_ciphersuites requires a 0-terminated + * list of supported ciphers + */ + if (ssock->param.ciphers_num > 0) { + unsigned i; + pj_ssl_cipher *ciphers; + ciphers = (pj_ssl_cipher*) + pj_pool_calloc(ssock->pool, ssock->param.ciphers_num + 1, + sizeof(pj_ssl_cipher)); + if (!ciphers) + return PJ_ENOMEM; + + for (i = 0; i < ssock->param.ciphers_num; ++i) + ciphers[i] = ssock->param.ciphers[i]; + + mbedtls_ssl_conf_ciphersuites(&mssock->ssl_config, ciphers); + } + + return PJ_SUCCESS; +} + +/* === SSL socket implementations === */ + +/* Allocate SSL backend struct */ +static pj_ssl_sock_t *ssl_alloc(pj_pool_t *pool) +{ + return (pj_ssl_sock_t *)PJ_POOL_ZALLOC_T(pool, mbedtls_sock_t); +} + +/* Create and initialize new SSL context and instance */ +static pj_status_t ssl_create(pj_ssl_sock_t *ssock) +{ + mbedtls_sock_t *mssock = (mbedtls_sock_t *)ssock; + const char *pers = "ssl_client"; + pj_status_t status; + int ret; + int endpoint; + /* This version string is 18 bytes long, as advised by version.h. */ + char version[18]; + + /* Suppress warnings */ + PJ_UNUSED_ARG(circ_reset); + PJ_UNUSED_ARG(circ_read_cancel); + PJ_UNUSED_ARG(get_ip_addr_ver); + + pj_assert(ssock); + + /* Initialize input circular buffer */ + status = circ_init(ssock->pool->factory, &ssock->circ_buf_input, 512); + if (status != PJ_SUCCESS) + return status; + + /* Initialize output circular buffer */ + status = circ_init(ssock->pool->factory, &ssock->circ_buf_output, 512); + if (status != PJ_SUCCESS) { + return status; + } + + mbedtls_version_get_string_full(version); + PJ_LOG(4, (THIS_FILE, "Mbed TLS version : %s", version)); + +#ifdef MBEDTLS_PSA_CRYPTO_C + ret = psa_crypto_init(); + if (ret != PSA_SUCCESS) { + PJ_LOG(1, (THIS_FILE, "Failed to initialize PSA Crypto, " + "ret = -0x%04X", ret)); + return PJ_EUNKNOWN; + } +#endif + + mbedtls_ssl_init(&mssock->ssl_ctx); + mbedtls_ssl_config_init(&mssock->ssl_config); + mbedtls_ctr_drbg_init(&mssock->ctr_drbg); + mbedtls_entropy_init(&mssock->entropy); + mbedtls_x509_crt_init(&mssock->cacert); + mbedtls_x509_crt_init(&mssock->cert); + mbedtls_pk_init(&mssock->pk_ctx); + + endpoint = ssock->is_server ? MBEDTLS_SSL_IS_SERVER + : MBEDTLS_SSL_IS_CLIENT; + ret = mbedtls_ssl_config_defaults(&mssock->ssl_config, endpoint, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT); + if (ret != 0) { + PJ_LOG(1, (THIS_FILE, "Failed to mbedtls_ssl_config_defaults, " + "ret = -0x%04X", -ret)); + goto out; + } + + ret = mbedtls_ctr_drbg_seed(&mssock->ctr_drbg, mbedtls_entropy_func, + &mssock->entropy, + (const unsigned char *)pers, strlen(pers)); + if (ret != 0) { + PJ_LOG(1, (THIS_FILE, "Failed to mbedtls_ctr_drbg_seed, " + "ret = -0x%04X", -ret)); + goto out; + } + + mbedtls_ssl_conf_rng(&mssock->ssl_config, + mbedtls_ctr_drbg_random, + &mssock->ctr_drbg); + + status = set_ssl_protocol(ssock); + if (status != PJ_SUCCESS) + return status; + + status = set_cert(ssock); + if (status != PJ_SUCCESS) + return status; + + status = set_cipher_list(ssock); + if (status != PJ_SUCCESS) + return status; + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_ssl_conf_dbg(&mssock->ssl_config, mbedtls_print_logs, NULL); + mbedtls_debug_set_threshold(MBEDTLS_DEBUG_VERBOSE); +#endif + + ret = mbedtls_ssl_setup(&mssock->ssl_ctx, &mssock->ssl_config); + if (ret != 0) { + PJ_LOG(1, (THIS_FILE, "Failed to mbedtls_ssl_setup, " + "ret = -0x%04X", -ret)); + goto out; + } + + if (!ssock->is_server && ssock->param.server_name.slen) { + ret = mbedtls_ssl_set_hostname(&mssock->ssl_ctx, + ssock->param.server_name.ptr); + if (ret != 0) { + PJ_LOG(1, (THIS_FILE, "Failed to mbedtls_ssl_set_hostname, " + "ret = -0x%04X", -ret)); + goto out; + } + } + + mbedtls_ssl_set_bio(&mssock->ssl_ctx, (void *)ssock, + (mbedtls_ssl_send_t *)ssl_data_push, + (mbedtls_ssl_recv_t *)ssl_data_pull, + NULL); + + ssl_ciphers_populate(); + + ret = 0; + +out: + return ssl_status_from_err(ssock, ret); +} + +/* Destroy MbedTLS credentials and session. */ +static void ssl_destroy(pj_ssl_sock_t *ssock) +{ + mbedtls_sock_t *mssock = (mbedtls_sock_t *)ssock; + + mbedtls_ssl_free(&mssock->ssl_ctx); + mbedtls_ssl_config_free(&mssock->ssl_config); + mbedtls_x509_crt_free(&mssock->cacert); + mbedtls_ctr_drbg_free(&mssock->ctr_drbg); + mbedtls_entropy_free(&mssock->entropy); + mbedtls_x509_crt_free(&mssock->cert); + mbedtls_pk_free(&mssock->pk_ctx); + +#ifdef MBEDTLS_PSA_CRYPTO_C + mbedtls_psa_crypto_free(); +#endif + + /* Destroy circular buffers */ + circ_deinit(&ssock->circ_buf_input); + circ_deinit(&ssock->circ_buf_output); +} + +/* Reset socket state. */ +static void ssl_reset_sock_state(pj_ssl_sock_t *ssock) +{ + pj_lock_acquire(ssock->circ_buf_output_mutex); + ssock->ssl_state = SSL_STATE_NULL; + pj_lock_release(ssock->circ_buf_output_mutex); + + ssl_close_sockets(ssock); +} + +static void ssl_ciphers_populate() +{ + const int *list; + + /* Populate once only */ + if (ssl_cipher_num) { + return; + } + + list = mbedtls_ssl_list_ciphersuites(); + + for (unsigned num = 0; + ssl_cipher_num < PJ_ARRAY_SIZE(ssl_ciphers) && list[num]; num++) { + const mbedtls_ssl_ciphersuite_t * const ciphersuite = + mbedtls_ssl_ciphersuite_from_id(list[num]); + if (!ciphersuite) + continue; + ssl_ciphers[ssl_cipher_num].name = + mbedtls_ssl_ciphersuite_get_name(ciphersuite); + ssl_ciphers[ssl_cipher_num].id = + mbedtls_ssl_ciphersuite_get_id(ciphersuite); + ssl_cipher_num++; + } +} + +static pj_ssl_cipher ssl_get_cipher(pj_ssl_sock_t *ssock) +{ + mbedtls_sock_t *mssock = (mbedtls_sock_t *)ssock; + + int id = mbedtls_ssl_get_ciphersuite_id_from_ssl(&mssock->ssl_ctx); + if (id != 0) { + return id; + } else { + return PJ_TLS_UNKNOWN_CIPHER; + } +} + +static void ssl_update_certs_info(pj_ssl_sock_t *ssock) +{ + mbedtls_sock_t *mssock = (mbedtls_sock_t *)ssock; + const mbedtls_x509_crt *crt; + + pj_assert(ssock->ssl_state == SSL_STATE_ESTABLISHED); + + /* Get active remote certificate */ + crt = mbedtls_ssl_get_peer_cert(&mssock->ssl_ctx); + if (crt) { + update_cert_info(crt, ssock->pool, &ssock->remote_cert_info); + } +} + +static void ssl_set_state(pj_ssl_sock_t *ssock, pj_bool_t is_server) +{ + PJ_UNUSED_ARG(ssock); + PJ_UNUSED_ARG(is_server); +} + +static void ssl_set_peer_name(pj_ssl_sock_t *ssock) +{ + /* Setting server name is done in ssl_create because ssl_create can handle + * errors returned from Mbed TLS APIs properly. + */ + PJ_UNUSED_ARG(ssock); +} + +/* Try to perform an asynchronous handshake */ +static pj_status_t ssl_do_handshake(pj_ssl_sock_t *ssock) +{ + mbedtls_sock_t *mssock = (mbedtls_sock_t *)ssock; + pj_status_t handshake_status; + pj_status_t status; + int ret; + + ret = mbedtls_ssl_handshake(&mssock->ssl_ctx); + handshake_status = ssl_status_from_err(ssock, ret); + + status = flush_circ_buf_output(ssock, &ssock->handshake_op_key, 0, 0); + if (status != PJ_SUCCESS) { + PJ_LOG(2, (THIS_FILE, "Failed to send handshake packets")); + return status; + } + if (handshake_status == PJ_EPENDING) + return PJ_EPENDING; + + + if (handshake_status != PJ_SUCCESS) { + PJ_LOG(2, (THIS_FILE, "Failed to mbedtls_ssl_handshake, " + "ret -0x%04X", -ret)); + return handshake_status; + } + + ssock->ssl_state = SSL_STATE_ESTABLISHED; + + return PJ_SUCCESS; +} + +static pj_status_t ssl_renegotiate(pj_ssl_sock_t *ssock) +{ + PJ_UNUSED_ARG(ssock); + + return PJ_SUCCESS; +} + +static pj_status_t ssl_read(pj_ssl_sock_t *ssock, void *data, int *size) +{ + mbedtls_sock_t *mssock = (mbedtls_sock_t *)ssock; + + int ret = mbedtls_ssl_read(&mssock->ssl_ctx, data, *size); + if (ret >= 0) { + *size = ret; + return PJ_SUCCESS; + } else if (ret == MBEDTLS_ERR_SSL_WANT_READ) { + *size = 0; + return PJ_SUCCESS; + } else { + return PJ_EUNKNOWN; + } +} + +static pj_status_t ssl_write(pj_ssl_sock_t *ssock, const void *data, + pj_ssize_t size, int *nwritten) +{ + mbedtls_sock_t *mssock = (mbedtls_sock_t *)ssock; + pj_status_t status; + pj_ssize_t nwritten_ = 0; + int ret; + + while (nwritten_ < size) { + ret = mbedtls_ssl_write(&mssock->ssl_ctx, + ((const unsigned char *)data) + nwritten_, + size - nwritten_); + if (ret < 0) { + status = ssl_status_from_err(ssock, ret); + + if (status == PJ_EPENDING) + continue; + + *nwritten = nwritten_; + PJ_LOG(2, (THIS_FILE, "Failed to mbedtls_ssl_write, " + "ret -0x%04X", -ret)); + return status; + } + + nwritten_ += ret; + } + + *nwritten = nwritten_; + return PJ_SUCCESS; +} + +#endif /* PJ_HAS_SSL_SOCK */ diff --git a/pjlib/src/pjlib-test/ssl_sock.c b/pjlib/src/pjlib-test/ssl_sock.c index 2ca31e9664..b3cbbb99fc 100644 --- a/pjlib/src/pjlib-test/ssl_sock.c +++ b/pjlib/src/pjlib-test/ssl_sock.c @@ -1718,10 +1718,14 @@ int ssl_sock_test(void) #endif #if WITH_BENCHMARK +#if (PJ_SSL_SOCK_IMP != PJ_SSL_SOCK_IMP_MBEDTLS) PJ_LOG(3,("", "..performance test")); ret = perf_test(PJ_IOQUEUE_MAX_HANDLES/2 - 1, 0); if (ret != 0) return ret; +#else + PJ_UNUSED_ARG(perf_test); +#endif #endif PJ_LOG(3,("", "..client non-SSL (handshake timeout 5 secs)")); From 149d0a8fcba0c9c1094f14e221eacbf6f17aa375 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Mon, 17 Feb 2025 15:59:41 +0700 Subject: [PATCH 2/8] Fix errors in building for shared libs (#4306) --- third_party/build/g7221/Makefile | 1 + third_party/build/gsm/Makefile | 1 + third_party/build/ilbc/Makefile | 1 + third_party/build/milenage/Makefile | 1 + third_party/build/webrtc/Makefile | 1 + third_party/build/webrtc_aec3/Makefile | 1 + third_party/build/yuv/Makefile | 1 + 7 files changed, 7 insertions(+) diff --git a/third_party/build/g7221/Makefile b/third_party/build/g7221/Makefile index d0e7596413..f4e5ca3243 100644 --- a/third_party/build/g7221/Makefile +++ b/third_party/build/g7221/Makefile @@ -32,6 +32,7 @@ export G7221_CODEC_OBJS = common/common.o common/huff_tab.o common/tables.o \ encode/dct4_a.o encode/sam2coef.o encode/encoder.o export G7221_CODEC_CFLAGS = $(_CFLAGS) +export G7221_CODEC_LDFLAGS = $(_LDFLAGS) export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT diff --git a/third_party/build/gsm/Makefile b/third_party/build/gsm/Makefile index 0b949982e3..cf027f7236 100644 --- a/third_party/build/gsm/Makefile +++ b/third_party/build/gsm/Makefile @@ -34,6 +34,7 @@ export GSM_CODEC_OBJS = add.o code.o decode.o \ export GSM_CODEC_CFLAGS = -DSASR -DWAV49 -DNeedFunctionPrototypes=1 $(_CFLAGS) +export GSM_CODEC_LDFLAGS += $(_LDFLAGS) export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT ############################################################################### diff --git a/third_party/build/ilbc/Makefile b/third_party/build/ilbc/Makefile index 39ac6b2b0d..28023a56ad 100644 --- a/third_party/build/ilbc/Makefile +++ b/third_party/build/ilbc/Makefile @@ -34,6 +34,7 @@ export ILBC_OBJS = FrameClassify.o LPCdecode.o LPCencode.o \ iLBC_decode.o iLBC_encode.o lsf.o \ packing.o syntFilter.o export ILBC_CFLAGS = $(_CFLAGS) +export ILBC_LDFLAGS = $(_LDFLAGS) export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT diff --git a/third_party/build/milenage/Makefile b/third_party/build/milenage/Makefile index 18a48b91af..7c3202eb11 100644 --- a/third_party/build/milenage/Makefile +++ b/third_party/build/milenage/Makefile @@ -27,6 +27,7 @@ export _LDFLAGS := $(CC_LDFLAGS) $(OS_LDFLAGS) $(M_LDFLAGS) $(HOST_LDFLAGS) \ export MILENAGE_SRCDIR = ../../milenage export MILENAGE_OBJS = milenage.o rijndael.o export MILENAGE_CFLAGS = $(_CFLAGS) +export MILENAGE_LDFLAGS = $(_LDFLAGS) export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT diff --git a/third_party/build/webrtc/Makefile b/third_party/build/webrtc/Makefile index 391e7786ab..3db223ee28 100644 --- a/third_party/build/webrtc/Makefile +++ b/third_party/build/webrtc/Makefile @@ -61,6 +61,7 @@ export WEBRTC_OBJS = \ export WEBRTC_CFLAGS = $(_CFLAGS) $(WEBRTC_OTHER_CFLAGS) export WEBRTC_CXXFLAGS = $(WEBRTC_CFLAGS) +export WEBRTC_LDFLAGS = $(_LDFLAGS) export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT diff --git a/third_party/build/webrtc_aec3/Makefile b/third_party/build/webrtc_aec3/Makefile index 95b445d8f8..016219aef3 100644 --- a/third_party/build/webrtc_aec3/Makefile +++ b/third_party/build/webrtc_aec3/Makefile @@ -168,6 +168,7 @@ export WEBRTC_AEC3_OBJS = \ export WEBRTC_AEC3_CFLAGS = $(_CFLAGS) $(WEBRTC_AEC3_OTHER_CFLAGS) export WEBRTC_AEC3_CXXFLAGS = $(WEBRTC_AEC3_CFLAGS) $(_CXXFLAGS) +export WEBRTC_AEC3_LDFLAGS = $(_LDFLAGS) export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT diff --git a/third_party/build/yuv/Makefile b/third_party/build/yuv/Makefile index 6d97e7f10b..7b11094fdc 100644 --- a/third_party/build/yuv/Makefile +++ b/third_party/build/yuv/Makefile @@ -72,6 +72,7 @@ export YUV_OBJS = \ export YUV_CFLAGS = -fomit-frame-pointer -fno-strict-aliasing -Wno-memset-elt-size -Wno-unknown-warning-option -Wno-pragmas $(_CFLAGS) export YUV_CXXFLAGS = -fomit-frame-pointer -fno-strict-aliasing -Wno-memset-elt-size -Wno-unknown-warning-option -Wno-pragmas $(_CXXFLAGS) +export YUV_LDFLAGS = $(_LDFLAGS) export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT From 8e979ddfbb4f723a06dfe69360733ebaa8626360 Mon Sep 17 00:00:00 2001 From: Amilcar Ubiera Date: Mon, 17 Feb 2025 23:22:36 -0500 Subject: [PATCH 3/8] pjsua_media: Fix to apply_med_update when PJMEDIA_HAS_VIDEO is disabled. (#4308) --- pjsip/src/pjsua-lib/pjsua_media.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index fe4fe65fc5..e4b2d44c9a 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -3940,11 +3940,6 @@ static pj_status_t apply_med_update(pjsua_call_media *call_med, pjsua_stream_info stream_info; pj_str_t *enc_name = NULL; - /* Sanity check. */ - PJ_ASSERT_RETURN(call_med->type == PJMEDIA_TYPE_AUDIO || - call_med->type == PJMEDIA_TYPE_VIDEO, - PJ_EINVAL); - if (call_med->type == PJMEDIA_TYPE_AUDIO) { si = (pjmedia_stream_info_common *)&asi; status = pjmedia_stream_info_from_sdp( @@ -3963,6 +3958,9 @@ static pj_status_t apply_med_update(pjsua_call_media *call_med, enc_name = &vsi.codec_info.encoding_name; #endif } + else { + status = PJMEDIA_EUNSUPMEDIATYPE; + } if (status != PJ_SUCCESS) { PJ_PERROR(1,(THIS_FILE, status, From 940e043ab58ae4258470c3dfec3fe02515e7de2c Mon Sep 17 00:00:00 2001 From: Amilcar Ubiera Date: Tue, 18 Feb 2025 00:21:17 -0500 Subject: [PATCH 4/8] ssl_sock_mbedtls: Fix to "incompatible types" warning when calling mbedtls_ssl_conf_ciphersuites. (#4309) --- pjlib/src/pj/ssl_sock_mbedtls.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pjlib/src/pj/ssl_sock_mbedtls.c b/pjlib/src/pj/ssl_sock_mbedtls.c index 8b4d4388f1..b75568e150 100644 --- a/pjlib/src/pj/ssl_sock_mbedtls.c +++ b/pjlib/src/pj/ssl_sock_mbedtls.c @@ -580,15 +580,15 @@ static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock) */ if (ssock->param.ciphers_num > 0) { unsigned i; - pj_ssl_cipher *ciphers; - ciphers = (pj_ssl_cipher*) + int *ciphers; + ciphers = (int*) pj_pool_calloc(ssock->pool, ssock->param.ciphers_num + 1, - sizeof(pj_ssl_cipher)); + sizeof(int)); if (!ciphers) return PJ_ENOMEM; for (i = 0; i < ssock->param.ciphers_num; ++i) - ciphers[i] = ssock->param.ciphers[i]; + ciphers[i] = (int)ssock->param.ciphers[i]; mbedtls_ssl_conf_ciphersuites(&mssock->ssl_config, ciphers); } From a57f587226f1626c10da85fd9e665747df4d8839 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Tue, 18 Feb 2025 12:39:35 +0700 Subject: [PATCH 5/8] Fix and update PJMEDIA_TRANSPORT_SWITCH_REMOTE_ADDR docs (#4310) - The docs is not shown due to a wrong Doxygen format. - Also updated the docs. --- pjmedia/include/pjmedia/config.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pjmedia/include/pjmedia/config.h b/pjmedia/include/pjmedia/config.h index 231fd7aaaa..f75029aa0a 100644 --- a/pjmedia/include/pjmedia/config.h +++ b/pjmedia/include/pjmedia/config.h @@ -1234,8 +1234,14 @@ #endif -/* Setting to determine if media transport should switch RTP and RTCP +/** + * Setting to determine if media transport should switch RTP and RTCP * remote address to the source address of the packets it receives. + * This feature is usually used for handling NAT traversal issues, + * also known as symmetric RTP and 'latching' techniques. + * + * See also run-time options #PJMEDIA_UDP_NO_SRC_ADDR_CHECKING and + * #PJMEDIA_ICE_NO_SRC_ADDR_CHECKING. * * By default it is enabled. */ From 6337fe394b7786af2f64cbc236993da649543f32 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Tue, 18 Feb 2025 12:39:57 +0700 Subject: [PATCH 6/8] Avoid deadlock in SIP transport shutdown (#4307) --- pjsip/src/pjsip/sip_transport.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c index 7ce617d4c7..4ef55843d9 100644 --- a/pjsip/src/pjsip/sip_transport.c +++ b/pjsip/src/pjsip/sip_transport.c @@ -1466,11 +1466,14 @@ PJ_DEF(pj_status_t) pjsip_transport_shutdown2(pjsip_transport *tp, pj_lock_acquire(tp->lock); mgr = tp->tpmgr; - pj_lock_acquire(mgr->lock); + + // Acquiring manager lock after transport lock may cause deadlock. + // And it does not seem necessary as well. + //pj_lock_acquire(mgr->lock); /* Do nothing if transport is being shutdown/destroyed already */ if (tp->is_shutdown || tp->is_destroying) { - pj_lock_release(mgr->lock); + //pj_lock_release(mgr->lock); pj_lock_release(tp->lock); return PJ_SUCCESS; } @@ -1501,7 +1504,7 @@ PJ_DEF(pj_status_t) pjsip_transport_shutdown2(pjsip_transport *tp, pjsip_transport_dec_ref(tp); } - pj_lock_release(mgr->lock); + //pj_lock_release(mgr->lock); pj_lock_release(tp->lock); return status; From 577d82b71c0b976cca70762783109825bbd68ef0 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Thu, 20 Feb 2025 09:38:33 +0700 Subject: [PATCH 7/8] Fix warnings by coverity & by msvc (#4315) Fix various warnings, e.g: unreachable code, uninitialized vars, unused var, signed/unsigned comparison --- pjsip/src/pjsip/sip_auth_client.c | 2 +- pjsip/src/pjsip/sip_transport.c | 2 +- pjsip/src/pjsip/sip_transport_tls.c | 3 ++- pjsip/src/pjsip/sip_util.c | 10 +++++++--- pjsip/src/pjsua-lib/pjsua_media.c | 15 +++++++++------ 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/pjsip/src/pjsip/sip_auth_client.c b/pjsip/src/pjsip/sip_auth_client.c index 31bf551e68..f50c489a62 100644 --- a/pjsip/src/pjsip/sip_auth_client.c +++ b/pjsip/src/pjsip/sip_auth_client.c @@ -108,7 +108,7 @@ const pjsip_auth_algorithm pjsip_auth_algorithms[] = { #define DO_ON_PARENT_LOCKED(sess, call) \ do { \ - pj_status_t on_parent; \ + pj_status_t on_parent = PJ_SUCCESS; \ pj_bool_t with_parent = PJ_FALSE; \ if (sess->parent) { \ pj_lock_acquire(sess->parent->lock); \ diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c index 4ef55843d9..6ccf410959 100644 --- a/pjsip/src/pjsip/sip_transport.c +++ b/pjsip/src/pjsip/sip_transport.c @@ -1488,7 +1488,7 @@ PJ_DEF(pj_status_t) pjsip_transport_shutdown2(pjsip_transport *tp, tp->is_shutdown = PJ_TRUE; /* Notify application of transport shutdown */ - state_cb = pjsip_tpmgr_get_state_cb(tp->tpmgr); + state_cb = pjsip_tpmgr_get_state_cb(mgr); if (state_cb) { pjsip_transport_state_info state_info; diff --git a/pjsip/src/pjsip/sip_transport_tls.c b/pjsip/src/pjsip/sip_transport_tls.c index 2079351979..18f92eaca9 100644 --- a/pjsip/src/pjsip/sip_transport_tls.c +++ b/pjsip/src/pjsip/sip_transport_tls.c @@ -931,9 +931,10 @@ static pj_status_t tls_create( struct tls_listener *listener, } if (addr) { + unsigned i; pj_memcpy( &tls->server_addr, addr, sizeof(pjsip_server_addresses)); - for (int i = 0; i < addr->count; ++i) { + for (i = 0; i < addr->count; ++i) { pj_strdup(pool, &tls->server_addr.entry[i].name, &addr->entry[i].name); } } diff --git a/pjsip/src/pjsip/sip_util.c b/pjsip/src/pjsip/sip_util.c index 076e643ecf..b5f64a7ff0 100644 --- a/pjsip/src/pjsip/sip_util.c +++ b/pjsip/src/pjsip/sip_util.c @@ -1369,9 +1369,10 @@ stateless_send_resolver_callback( pj_status_t status, /* Copy server addresses */ if (addr && addr != &tdata->dest_info.addr) { + unsigned i; pj_memcpy( &tdata->dest_info.addr, addr, sizeof(pjsip_server_addresses)); - for (int i = 0; i < addr->count; ++i) { + for (i = 0; i < addr->count; ++i) { pj_strdup(tdata->pool, &tdata->dest_info.addr.entry[i].name, &addr->entry[i].name); } } @@ -1804,6 +1805,7 @@ static void send_response_resolver_cb( pj_status_t status, void *token, const pjsip_server_addresses *addr ) { pjsip_send_state *send_state = (pjsip_send_state*) token; + unsigned i; if (status != PJ_SUCCESS) { if (send_state->app_cb) { @@ -1835,8 +1837,10 @@ static void send_response_resolver_cb( pj_status_t status, void *token, /* Update address in send_state. */ pj_memcpy(&send_state->tdata->dest_info.addr, addr, sizeof(*addr)); - for (int i = 0; i < send_state->tdata->dest_info.addr.count; ++i) { - pj_strdup(send_state->tdata->pool, &send_state->tdata->dest_info.addr.entry[i].name, &addr->entry[i].name); + for (i = 0; i < send_state->tdata->dest_info.addr.count; ++i) { + pj_strdup(send_state->tdata->pool, + &send_state->tdata->dest_info.addr.entry[i].name, + &addr->entry[i].name); } /* Send response using the transoprt. */ diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index e4b2d44c9a..1fcbef68ae 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -3932,12 +3932,16 @@ static pj_status_t apply_med_update(pjsua_call_media *call_med, pj_pool_t *tmp_pool = call->inv->pool_prov; pj_status_t status = PJ_SUCCESS; - pjmedia_stream_info asi; + /* Initialize the following variables to avoid warnings from compiler + * and code analysis. Actually the function will always init the vars + * when the media type is valid/recognized. + */ + pjmedia_stream_info asi = {0}; #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) - pjmedia_vid_stream_info vsi; + pjmedia_vid_stream_info vsi = {0}; #endif - pjmedia_stream_info_common *si; - pjsua_stream_info stream_info; + pjmedia_stream_info_common *si = NULL; + pjsua_stream_info stream_info = {0}; pj_str_t *enc_name = NULL; if (call_med->type == PJMEDIA_TYPE_AUDIO) { @@ -4231,8 +4235,7 @@ static pj_status_t apply_med_update(pjsua_call_media *call_med, } len = pj_ansi_snprintf( info+info_len, sizeof(info)-info_len, ", stream #%d: %.*s (%s)", mi, - (enc_name? (int)enc_name->slen: 0), - (enc_name? enc_name->ptr: info), + (int)enc_name->slen, enc_name->ptr, dir); if (len > 0) info_len += len; From 5ce1ba679da0f08652a742b51a02652a9d7fdec7 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Fri, 21 Feb 2025 09:02:09 +0700 Subject: [PATCH 8/8] Update media change detection for H264 (#4317) --- pjsip/src/pjsua-lib/pjsua_media.c | 38 +++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index 1fcbef68ae..ce988d26df 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -18,6 +18,7 @@ */ #include #include +#include #define THIS_FILE "pjsua_media.c" @@ -3876,15 +3877,42 @@ static pj_bool_t is_media_changed(const pjsua_call *call, return PJ_TRUE; } - /* Compare codec param */ - if (/* old_cp->enc_mtu != new_cp->enc_mtu || */ - pj_memcmp(&old_cp->enc_fmt.det, &new_cp->enc_fmt.det, - sizeof(pjmedia_video_format_detail)) || - !match_codec_fmtp(&old_cp->dec_fmtp, &new_cp->dec_fmtp) || + /* Compare SDP fmtp for both directions */ + if (!match_codec_fmtp(&old_cp->dec_fmtp, &new_cp->dec_fmtp) || !match_codec_fmtp(&old_cp->enc_fmtp, &new_cp->enc_fmtp)) { return PJ_TRUE; } + + /* Compare format for encoding only */ + if (pj_memcmp(&old_cp->enc_fmt.det, &new_cp->enc_fmt.det, + sizeof(pjmedia_video_format_detail))) + { + /* For H264, resolution may be adjusted to remote's profile-level, + * so check if it is different because of the adjusted format. + */ + if (pj_strcmp2(&new_ci->encoding_name, "H264") == 0) { + pjmedia_vid_codec_param param = {0}; + pj_status_t status; + + param.dir = PJMEDIA_DIR_ENCODING; + pj_memcpy(¶m.enc_fmt, &new_cp->enc_fmt, + sizeof(param.enc_fmt)); + pj_memcpy(¶m.enc_fmtp,&new_cp->enc_fmtp, + sizeof(param.enc_fmtp)); + status = pjmedia_vid_codec_h264_apply_fmtp(¶m); + if (status != PJ_SUCCESS) + return PJ_TRUE; + + if (pj_memcmp(&old_cp->enc_fmt.det, ¶m.enc_fmt.det, + sizeof(pjmedia_video_format_detail))) + { + return PJ_TRUE; + } + } else { + return PJ_TRUE; + } + } } #endif