Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ jobs:
jobs="$(nproc 2>/dev/null || sysctl -n hw.ncpu)"
make -j"$jobs"

mbedtls-4:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6

- name: Install dependencies
run: brew install mbedtls libsodium libuv c-ares pcre2

- name: Build
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DSS_DEPENDENCY_MODE=system -DWITH_STATIC=OFF \
-DCMAKE_PREFIX_PATH="$(brew --prefix mbedtls)"
cmake --build build -j"$(sysctl -n hw.ncpu)"

- name: CTest
run: ctest --test-dir build -LE memcheck --output-on-failure --no-tests=error

debian-package:
runs-on: ubuntu-latest
steps:
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,9 @@ IPv4/IPv6 CIDRs, `full:example.com` for exact domains, and
case and respect label boundaries. Unsupported regex rules are rejected.

Distribution packages can use `-DSS_DEPENDENCY_MODE=system -DWITH_STATIC=OFF`
with libuv, c-ares, libsodium, Mbed TLS 3.x, and PCRE2 development packages.
Use `-DCMAKE_PREFIX_PATH=/opt/homebrew/opt/mbedtls@3` when needed on macOS.
with libuv, c-ares, libsodium, Mbed TLS (2.x, 3.x or 4.x), and PCRE2
development packages. Use `-DCMAKE_PREFIX_PATH=/opt/homebrew/opt/mbedtls@3`
when needed on macOS.

| Option | Default | Purpose |
|---|---|---|
Expand Down Expand Up @@ -334,7 +335,7 @@ The OpenWRT project is maintained here:

Use the bundled CMake instructions above with Xcode Command Line Tools and
CMake. The bundled executables require no Homebrew runtime libraries.
For system mode, use Mbed TLS 3 and point `CMAKE_PREFIX_PATH` at its prefix.
For system mode, use Mbed TLS 3 or 4 and point `CMAKE_PREFIX_PATH` at its prefix.

### Windows (MinGW)

Expand Down
73 changes: 48 additions & 25 deletions cmake/FindMbedTLS.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# MBEDTLS_FOUND
# MBEDTLS_INCLUDE_DIRS
# MBEDTLS_CRYPTO_LIBRARY
# MBEDTLS_CRYPTO_LIBRARY_NAME (tfpsacrypto for Mbed TLS 4.x, else mbedcrypto)
# MBEDTLS_TLS_LIBRARY
#
# The headers and the libraries MUST come from the same installation. Mixing
Expand All @@ -16,7 +17,10 @@

include(CheckCSourceCompiles)

# This codebase targets the mbedTLS 3.x API, so prefer a 3.x installation.
# Mbed TLS 4.x moved the crypto library to TF-PSA-Crypto (libtfpsacrypto)
# and made mbedtls/cipher.h private, so look for mbedtls/version.h, which all
# versions install. Keep preferring the keg-only 3.x on Homebrew, which has
# been tested longer.
set(_MBEDTLS_PREFIX_HINTS
${MbedTLS_ROOT}
${CMAKE_PREFIX_PATH}
Expand All @@ -33,9 +37,9 @@ set(_MBEDTLS_PREFIX_HINTS
# two can never be drawn from different installations.
if(NOT CMAKE_CROSSCOMPILING)
foreach(_prefix IN LISTS _MBEDTLS_PREFIX_HINTS)
if(EXISTS "${_prefix}/include/mbedtls/cipher.h")
if(EXISTS "${_prefix}/include/mbedtls/version.h")
find_library(_MBEDTLS_CRYPTO_IN_PREFIX
NAMES mbedcrypto
NAMES tfpsacrypto mbedcrypto
PATHS "${_prefix}/lib" "${_prefix}/lib/${CMAKE_LIBRARY_ARCHITECTURE}"
NO_DEFAULT_PATH
)
Expand All @@ -51,12 +55,12 @@ endif()
if(_MBEDTLS_ROOT)
# Pin every component to the prefix chosen above.
find_path(MBEDTLS_INCLUDE_DIR
NAMES mbedtls/cipher.h
NAMES mbedtls/version.h
PATHS "${_MBEDTLS_ROOT}/include"
NO_DEFAULT_PATH
)
find_library(MBEDTLS_CRYPTO_LIBRARY
NAMES mbedcrypto
NAMES tfpsacrypto mbedcrypto
PATHS "${_MBEDTLS_ROOT}/lib" "${_MBEDTLS_ROOT}/lib/${CMAKE_LIBRARY_ARCHITECTURE}"
NO_DEFAULT_PATH
)
Expand All @@ -67,8 +71,8 @@ if(_MBEDTLS_ROOT)
)
else()
# No single prefix provided both; fall back to a plain search.
find_path(MBEDTLS_INCLUDE_DIR NAMES mbedtls/cipher.h)
find_library(MBEDTLS_CRYPTO_LIBRARY NAMES mbedcrypto)
find_path(MBEDTLS_INCLUDE_DIR NAMES mbedtls/version.h)
find_library(MBEDTLS_CRYPTO_LIBRARY NAMES tfpsacrypto mbedcrypto)
find_library(MBEDTLS_TLS_LIBRARY NAMES mbedtls)
endif()

Expand All @@ -85,36 +89,55 @@ if(MBEDTLS_INCLUDE_DIR AND MBEDTLS_CRYPTO_LIBRARY)
file(STRINGS "${_mbedtls_version_header}" _mbedtls_version_line
REGEX "^#define MBEDTLS_VERSION_STRING +\"[0-9.]+\"")
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" MBEDTLS_VERSION "${_mbedtls_version_line}")
if(NOT MBEDTLS_VERSION OR MBEDTLS_VERSION VERSION_LESS 2 OR NOT MBEDTLS_VERSION VERSION_LESS 4)
message(FATAL_ERROR "Supported system Mbed TLS versions are 2.x and 3.x; found ${MBEDTLS_VERSION}")
if(NOT MBEDTLS_VERSION OR MBEDTLS_VERSION VERSION_LESS 2 OR NOT MBEDTLS_VERSION VERSION_LESS 5)
message(FATAL_ERROR "Supported system Mbed TLS versions are 2.x, 3.x and 4.x; found ${MBEDTLS_VERSION}")
endif()
if(MBEDTLS_VERSION VERSION_LESS 4)
set(MBEDTLS_CRYPTO_LIBRARY_NAME mbedcrypto)
else()
set(MBEDTLS_CRYPTO_LIBRARY_NAME tfpsacrypto)
endif()

set(CMAKE_REQUIRED_INCLUDES ${MBEDTLS_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${MBEDTLS_CRYPTO_LIBRARY})

# Check for required CFB mode support
check_c_source_compiles("
#include <mbedtls/cipher.h>
#if !defined(MBEDTLS_CIPHER_MODE_CFB)
#error CFB mode not supported
#endif
int main(void) { return 0; }
" MBEDTLS_HAS_CFB)

if(NOT MBEDTLS_HAS_CFB)
# Try mbedtls 3.x config path
if(NOT MBEDTLS_VERSION VERSION_LESS 4)
check_c_source_compiles("
#include <psa/crypto.h>
#if !defined(PSA_WANT_ALG_CFB)
#error CFB mode not supported
#endif
int main(void) { return 0; }
" MBEDTLS_HAS_CFB_PSA)
if(NOT MBEDTLS_HAS_CFB_PSA)
message(FATAL_ERROR "Mbed TLS found but PSA_WANT_ALG_CFB is not enabled. "
"Please enable CFB mode in your TF-PSA-Crypto configuration.")
endif()
else()
check_c_source_compiles("
#include <mbedtls/build_info.h>
#include <mbedtls/cipher.h>
#if !defined(MBEDTLS_CIPHER_MODE_CFB)
#error CFB mode not supported
#endif
int main(void) { return 0; }
" MBEDTLS_HAS_CFB_V3)

if(NOT MBEDTLS_HAS_CFB_V3)
message(FATAL_ERROR "mbedTLS found but MBEDTLS_CIPHER_MODE_CFB is not enabled. "
"Please enable CFB mode in your mbedTLS configuration.")
" MBEDTLS_HAS_CFB)

if(NOT MBEDTLS_HAS_CFB)
# Try mbedtls 3.x config path
check_c_source_compiles("
#include <mbedtls/build_info.h>
#include <mbedtls/cipher.h>
#if !defined(MBEDTLS_CIPHER_MODE_CFB)
#error CFB mode not supported
#endif
int main(void) { return 0; }
" MBEDTLS_HAS_CFB_V3)

if(NOT MBEDTLS_HAS_CFB_V3)
message(FATAL_ERROR "mbedTLS found but MBEDTLS_CIPHER_MODE_CFB is not enabled. "
"Please enable CFB mode in your mbedTLS configuration.")
endif()
endif()
endif()

Expand Down
2 changes: 1 addition & 1 deletion cmake/InstallPackage.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ if(SS_BUILD_STATIC_LIBRARY)
endif()
list(APPEND private_links "\${SODIUM_LIBRARY}" "\${MBEDTLS_CRYPTO_LIBRARY}"
"\${CARES_LIBRARY}" )
string(APPEND SS_PC_PRIVATE " -lsodium -lmbedcrypto -lcares")
string(APPEND SS_PC_PRIVATE " -lsodium -l${MBEDTLS_CRYPTO_LIBRARY_NAME} -lcares")
install(FILES cmake/FindMbedTLS.cmake cmake/FindSodium.cmake
cmake/FindCares.cmake cmake/FindPCRE2.cmake cmake/mbedtls_version_check.c
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/shadowsocks-c/modules)
Expand Down
25 changes: 25 additions & 0 deletions cmake/mbedtls_version_check.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,29 @@

#include <mbedtls/version.h>

#if MBEDTLS_VERSION_NUMBER >= 0x04000000
/*
* Mbed TLS 4.x has the crypto in TF-PSA-Crypto, which has its own version.
* mbedtls_version_get_string() is in libmbedtls, which isn't linked.
*/
#include <tf-psa-crypto/version.h>

int
main(void)
{
const char *runtime = tf_psa_crypto_version_get_string();

if (strcmp(runtime, TF_PSA_CRYPTO_VERSION_STRING) != 0) {
printf("headers say TF-PSA-Crypto %s, library reports %s",
TF_PSA_CRYPTO_VERSION_STRING, runtime);
return 1;
}

return 0;
}

#else

int
main(void)
{
Expand All @@ -27,3 +50,5 @@ main(void)

return 0;
}

#endif
34 changes: 11 additions & 23 deletions src/aead.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,8 @@ aead_cipher_encrypt(cipher_ctx_t *cipher_ctx,
case AES128GCM:
case AES128GCM2022:
case AES256GCM2022:
#if MBEDTLS_VERSION_NUMBER < 0x03000000
err = mbedtls_cipher_auth_encrypt(cipher_ctx->evp, n, nlen, ad, adlen,
m, mlen, c, clen, c + mlen, tlen);
*clen += tlen;
#else
err = mbedtls_cipher_auth_encrypt_ext(cipher_ctx->evp, n, nlen, ad, adlen,
m, mlen, c, mlen + tlen, clen, tlen);
#endif
err = crypto_cipher_auth_encrypt(cipher_ctx->evp, n, nlen, ad, adlen,
m, mlen, c, clen, tlen);
break;
case CHACHA20POLY1305IETF:
case CHACHA20POLY1305IETF2022:
Expand Down Expand Up @@ -237,13 +231,8 @@ aead_cipher_decrypt(cipher_ctx_t *cipher_ctx,
case AES128GCM:
case AES128GCM2022:
case AES256GCM2022:
#if MBEDTLS_VERSION_NUMBER < 0x03000000
err = mbedtls_cipher_auth_decrypt(cipher_ctx->evp, n, nlen, ad, adlen,
m, mlen - tlen, p, plen, m + mlen - tlen, tlen);
#else
err = mbedtls_cipher_auth_decrypt_ext(cipher_ctx->evp, n, nlen, ad, adlen,
m, mlen, p, mlen - tlen, plen, tlen);
#endif
err = crypto_cipher_auth_decrypt(cipher_ctx->evp, n, nlen, ad, adlen,
m, mlen, p, plen, tlen);
break;
case CHACHA20POLY1305IETF:
case CHACHA20POLY1305IETF2022:
Expand Down Expand Up @@ -295,7 +284,7 @@ aead_get_cipher_type(int method)
ciphername);
return NULL;
}
return mbedtls_cipher_info_from_string(mbedtlsname);
return crypto_cipher_info_from_string(mbedtlsname);
}

void
Expand All @@ -306,7 +295,7 @@ aead_cipher_ctx_set_key(cipher_ctx_t *cipher_ctx, int enc)
cipher_ctx->salt, cipher_ctx->cipher->key_len,
cipher_ctx->skey, cipher_ctx->cipher->key_len);
} else {
const digest_type_t *md = mbedtls_md_info_from_string("SHA1");
const digest_type_t *md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
if (md == NULL) {
FATAL("SHA1 Digest not found in crypto library");
}
Expand Down Expand Up @@ -334,11 +323,11 @@ aead_cipher_ctx_set_key(cipher_ctx_t *cipher_ctx, int enc)
}
return;
}
if (mbedtls_cipher_setkey(cipher_ctx->evp, cipher_ctx->skey,
cipher_ctx->cipher->key_len * 8, enc) != 0) {
if (crypto_cipher_setkey(cipher_ctx->evp, cipher_ctx->skey,
cipher_ctx->cipher->key_len, enc) != 0) {
FATAL("Cannot set mbed TLS cipher key");
}
if (mbedtls_cipher_reset(cipher_ctx->evp) != 0) {
if (crypto_cipher_reset(cipher_ctx->evp) != 0) {
FATAL("Cannot finish preparation of mbed TLS cipher context");
}
}
Expand Down Expand Up @@ -367,8 +356,7 @@ aead_cipher_ctx_init(cipher_ctx_t *cipher_ctx, int method, int enc)
cipher_ctx->evp = ss_malloc(sizeof(cipher_evp_t));
memset(cipher_ctx->evp, 0, sizeof(cipher_evp_t));
cipher_evp_t *evp = cipher_ctx->evp;
mbedtls_cipher_init(evp);
if (mbedtls_cipher_setup(evp, cipher) != 0) {
if (crypto_cipher_setup(evp, cipher) != 0) {
FATAL("Cannot initialize mbed TLS cipher context");
}
}
Expand Down Expand Up @@ -415,7 +403,7 @@ aead_ctx_release(cipher_ctx_t *cipher_ctx)
return;
}

mbedtls_cipher_free(cipher_ctx->evp);
crypto_cipher_free(cipher_ctx->evp);
ss_free(cipher_ctx->evp);
}

Expand Down
Loading