diff --git a/net/curl-impersonate/Portfile b/net/curl-impersonate/Portfile new file mode 100644 index 0000000000000..bb8a980a4d263 --- /dev/null +++ b/net/curl-impersonate/Portfile @@ -0,0 +1,207 @@ +# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:et:sw=4:ts=4:sts=4 + +PortSystem 1.0 +PortGroup cmake 1.1 +PortGroup github 1.0 +PortGroup legacysupport 1.1 + +legacysupport.newest_darwin_requires_legacy 16 +# Pre-10.12 Apple libc++ does not support all needed features. +# This does not affect macOS versions using libsdtc++. +legacysupport.use_mp_libcxx yes + +github.setup lexiforest curl-impersonate 2.0.0 v +revision 0 +categories net www +maintainers {@barracuda156 macos-powerpc.org:barracuda} openmaintainer +license MIT + +description active fork of curl-impersonate with more versions and build targets +long_description \ + An {*}${description}. + +distname ${github.project}-${version} +github.tarball_from archive + +# curl-impersonate uses specific versions of dependencies and links them statically. +# See: https://github.com/lexiforest/curl-impersonate/blob/ec41b71ce888806bfec56ada7a7258d333eb3d19/CMakeLists.txt +set boringssl_hash 156c7b75ae9b8c3b3f847acf264f17594c3859fb +set brotli_version 1.2.0 +set curl_version 8.21.0 +set libidn_version 2.3.7 +set nghttp2_version 1.63.0 +set nghttp3_version 1.15.0 +set ngtcp2_version 1.20.0 +set zlib_version 1.3.1 +set zstd_version 1.5.7 + +set curl_tag [string map {. _} ${curl_version}] + +distfiles-append \ + ${boringssl_hash}${extract.suffix}:boringssl \ + v${brotli_version}${extract.suffix}:brotli \ + curl-${curl_tag}${extract.suffix}:curl \ + libidn2-${libidn_version}${extract.suffix}:libidn \ + v${nghttp2_version}${extract.suffix}:nghttp2 \ + nghttp3-${nghttp3_version}${extract.suffix}:nghttp3 \ + ngtcp2-${ngtcp2_version}${extract.suffix}:ngtcp2 \ + zlib-${zlib_version}${extract.suffix}:zlib \ + zstd-${zstd_version}${extract.suffix}:zstd + +master_sites-append \ + https://github.com/google/boringssl/archive/:boringssl \ + https://github.com/google/brotli/archive/refs/tags/:brotli \ + https://github.com/curl/curl/archive/refs/tags/:curl \ + https://ftp.gnu.org/gnu/libidn/:libidn \ + https://github.com/nghttp2/nghttp2/archive/refs/tags/:nghttp2 \ + https://github.com/ngtcp2/nghttp3/releases/download/v${nghttp3_version}/:nghttp3 \ + https://github.com/ngtcp2/ngtcp2/releases/download/v${ngtcp2_version}/:ngtcp2 \ + https://github.com/madler/zlib/releases/download/v${zlib_version}/:zlib \ + https://github.com/facebook/zstd/releases/download/v${zstd_version}/:zstd + +checksums ${distname}${extract.suffix} \ + rmd160 7b86ca2cb6132bedd2d91fc44ff7c875d3d160cb \ + sha256 a9827cfce8246e78b86e26f012ae9fcb9bc05822009cd7ce4c9e130af6bdfb6f \ + size 207780 \ + ${boringssl_hash}${extract.suffix} \ + rmd160 2606447aeebd42ef2ee5fc948713f0aa3666450b \ + sha256 4cbd70611e6400616fd5a58f42e19e7bafd568c674ecb3a6418c43ae1e3ac93b \ + size 74515087 \ + v${brotli_version}${extract.suffix} \ + rmd160 949e0c56045b760b854714f45b0912936a9be53a \ + sha256 816c96e8e8f193b40151dad7e8ff37b1221d019dbcb9c35cd3fadbfe6477dfec \ + size 646315 \ + curl-${curl_tag}${extract.suffix} \ + rmd160 bb9ba1116f1ce6e91fa609d6a5d6803f614c9aae \ + sha256 ec753aa6f408a3ca9f0d6d5f7a77417aecd1544db13c03ae5d443612bf367364 \ + size 3592963 \ + libidn2-${libidn_version}${extract.suffix} \ + rmd160 511eb10830342dc546824c5e48bb6ef0022382ab \ + sha256 4c21a791b610b9519b9d0e12b8097bf2f359b12f8dd92647611a929e6bfd7d64 \ + size 2155214 \ + v${nghttp2_version}${extract.suffix} \ + rmd160 fa3d04976a104cf66338997f6fa55d1c465623d6 \ + sha256 f3da0627bee7a6a60f5a4eb6de8d17d25e99f50f87b0fc0c20676c682bf31098 \ + size 1070155 \ + nghttp3-${nghttp3_version}${extract.suffix} \ + rmd160 37d60d4b7c56836ec03cb94bd2a528781b40c6ab \ + sha256 0e431c81eb2d3df5ced048d6e942925ff922ad053e76a0274eea7b164c9b776e \ + size 655937 \ + ngtcp2-${ngtcp2_version}${extract.suffix} \ + rmd160 839f587fb815485782b20d8891bf718a5db1af56 \ + sha256 daa3398640a1fe1823ad8e2b1b88562b8da7888a47edd8c8ba03c75cfd9c8bb6 \ + size 1204305 \ + zlib-${zlib_version}${extract.suffix} \ + rmd160 52945a1a5a1bd51ac676a0b9197bdaacbc537fd6 \ + sha256 9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23 \ + size 1512791 \ + zstd-${zstd_version}${extract.suffix} \ + rmd160 9a07d2d7b2cc9c6acd48dbf593ae1bace4590c94 \ + sha256 eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 \ + size 2434947 + +set dep_src_dir ${worksrcpath}/deps/src +set dep_build_dir ${worksrcpath}/deps/build +set dep_inst_dir ${worksrcpath}/deps/install + +post-extract { + xinstall -d ${dep_src_dir} + + move ${workpath}/boringssl-${boringssl_hash} ${dep_src_dir}/boringssl + move ${workpath}/brotli-${brotli_version} ${dep_src_dir}/brotli + move ${workpath}/curl-curl-${curl_tag} ${dep_src_dir}/curl + move ${workpath}/libidn2-${libidn_version} ${dep_src_dir}/libidn2 + move ${workpath}/nghttp2-${nghttp2_version} ${dep_src_dir}/nghttp2 + move ${workpath}/nghttp3-${nghttp3_version} ${dep_src_dir}/nghttp3 + move ${workpath}/ngtcp2-${ngtcp2_version} ${dep_src_dir}/ngtcp2 + move ${workpath}/zlib-${zlib_version} ${dep_src_dir}/zlib + move ${workpath}/zstd-${zstd_version} ${dep_src_dir}/zstd +} + +cmake.out_of_source no +cmake.generator Ninja + +set py_ver 3.14 +set py_ver_nodot [string map {. {}} ${py_ver}] +configure.python ${prefix}/bin/python${py_ver} + +# Prefer system libiconv, it works fine back to powerpc: +set iconv_prefix /usr +# macOS 11+ do not have libiconv in filesystem however, so there we need a port: +if {${os.platform} eq "darwin" && ${os.major} > 19} { + set iconv_prefix ${prefix} + depends_lib-append port:libiconv +} + +depends_build-append \ + port:autoconf \ + port:automake \ + port:libtool \ + path:bin/perl:perl5 \ + path:bin/pkg-config:pkgconfig + +depends_run-append path:share/curl/curl-ca-bundle.crt:curl-ca-bundle + +compiler.c_standard 2011 +compiler.cxx_standard 2020 + +patch.pre_args-replace -p0 -p1 + +patchfiles-append 0001-CMakeLists.patch \ + 0002-libiconv.patch \ + 0003-boringssl.patch + +if {${os.major} < 11 && [string match *gcc* ${configure.compiler}]} { + patchfiles-append 0004-zstd.patch +} + +post-patch { + reinplace "s,@PREFIX@,${prefix},g" ${worksrcpath}/CMakeLists.txt + reinplace "s,@ICONV_PREFIX@,${iconv_prefix}," ${worksrcpath}/CMakeLists.txt +} + +configure.pre_args-replace \ + -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=ON \ + -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=OFF + +# Defaults which normal curl uses as well: +configure.args-append \ + -DCURL_CA_BUNDLE=${prefix}/share/curl/curl-ca-bundle.crt \ + -DCURL_SUBPROJECT_FORCE_OPENSSL_PATHS=ON \ + -DUSE_APPLE_SECTRUST=OFF \ + -DUSE_LIBIDN2=ON + +# asm does not exist for powerpc in boringssl and may not exist/work on other exotic archs. +if {${configure.build_arch} ni [list arm64 x86_64]} { + configure.args-append \ + -DDISABLE_BORINGSSL_ASM=ON +} + +if {${cxx_stdlib} eq "libc++"} { + configure.args-append \ + -DCURL_IMPERSONATE_CXX_RUNTIME_LIBRARY:STRING=c++ +} else { + configure.args-append \ + -DCURL_IMPERSONATE_CXX_RUNTIME_LIBRARY:STRING=stdc++ +} + +# USE_LIBIDN2 requires prebuilt libidn2, which upstream does with a standalone script. +pre-configure { + xinstall -d ${dep_build_dir}/libidn2 + system -W ${dep_build_dir}/libidn2 "PKG_CONFIG_PATH=\"${dep_inst_dir}/lib/pkgconfig\" \ + CPPFLAGS= LDFLAGS= LIBRARY_PATH= \ + ${dep_src_dir}/libidn2/configure --prefix=${worksrcpath}/deps/install --disable-nls \ + --disable-shared --enable-static --with-pic --with-included-libunistring \ + --with-libiconv-prefix=${iconv_prefix} --without-libintl-prefix && make V=1 MAKEFLAGS=-j${build.jobs} && make install MAKEFLAGS=" +} + +universal_variant no + +post-destroot { + move ${destroot}${prefix}/include/curl ${destroot}${prefix}/include/${name} + platform darwin { + set dlib ${prefix}/lib/lib${name}.dylib + system "install_name_tool -id ${dlib} ${destroot}${dlib}" + system "install_name_tool -change @rpath/libcurl-impersonate.4.dylib ${dlib} ${destroot}${prefix}/bin/${name}" + } +} diff --git a/net/curl-impersonate/files/0001-CMakeLists.patch b/net/curl-impersonate/files/0001-CMakeLists.patch new file mode 100644 index 0000000000000..983cbd204763a --- /dev/null +++ b/net/curl-impersonate/files/0001-CMakeLists.patch @@ -0,0 +1,118 @@ +--- a/CMakeLists.txt 2026-07-26 12:23:17.000000000 +0800 ++++ b/CMakeLists.txt 2026-08-05 17:40:54.000000000 +0800 +@@ -184,8 +184,7 @@ + + # zlib + ExternalProject_Add(zlib +- URL "${ZLIB_URL}" +- URL_HASH "${ZLIB_URL_HASH}" ++ DOWNLOAD_COMMAND "" + SOURCE_DIR "${DEPS_SRC_DIR}/zlib" + BINARY_DIR "${DEPS_BUILD_DIR}/zlib" + INSTALL_DIR "${DEPS_INSTALL_DIR}" +@@ -199,8 +198,7 @@ + + # zstd + ExternalProject_Add(zstd +- URL "${ZSTD_URL}" +- URL_HASH "${ZSTD_URL_HASH}" ++ DOWNLOAD_COMMAND "" + SOURCE_DIR "${DEPS_SRC_DIR}/zstd" + BINARY_DIR "${DEPS_BUILD_DIR}/zstd" + INSTALL_DIR "${DEPS_INSTALL_DIR}" +@@ -219,8 +217,7 @@ + # brotli + _track_external_project_patch(brotli _brotli_patch_file _brotli_patch_changed) + ExternalProject_Add(brotli +- URL "${BROTLI_URL}" +- URL_HASH "${BROTLI_URL_HASH}" ++ DOWNLOAD_COMMAND "" + SOURCE_DIR "${DEPS_SRC_DIR}/brotli" + BINARY_DIR "${DEPS_BUILD_DIR}/brotli" + INSTALL_DIR "${DEPS_INSTALL_DIR}" +@@ -263,8 +260,7 @@ + boringssl _boringssl_patch_file _boringssl_patch_changed + ) + ExternalProject_Add(boringssl +- URL "${BORINGSSL_URL}" +- URL_HASH "${BORINGSSL_URL_HASH}" ++ DOWNLOAD_COMMAND "" + SOURCE_DIR "${DEPS_SRC_DIR}/boringssl" + BINARY_DIR "${DEPS_BUILD_DIR}/boringssl" + PATCH_COMMAND ${PATCH_EXE} -p1 -i "${_boringssl_patch_file}" +@@ -292,8 +288,7 @@ + + # nghttp2 + ExternalProject_Add(nghttp2 +- URL "${NGHTTP2_URL}" +- URL_HASH "${NGHTTP2_URL_HASH}" ++ DOWNLOAD_COMMAND "" + SOURCE_DIR "${DEPS_SRC_DIR}/nghttp2" + BINARY_DIR "${DEPS_BUILD_DIR}/nghttp2" + INSTALL_DIR "${DEPS_INSTALL_DIR}" +@@ -314,8 +309,7 @@ + # nghttp3 + _track_external_project_patch(nghttp3 _nghttp3_patch_file _nghttp3_patch_changed) + ExternalProject_Add(nghttp3 +- URL "${NGHTTP3_URL}" +- URL_HASH "${NGHTTP3_URL_HASH}" ++ DOWNLOAD_COMMAND "" + SOURCE_DIR "${DEPS_SRC_DIR}/nghttp3" + BINARY_DIR "${DEPS_BUILD_DIR}/nghttp3" + INSTALL_DIR "${DEPS_INSTALL_DIR}" +@@ -347,8 +341,7 @@ + endif() + ExternalProject_Add(ngtcp2 + LIST_SEPARATOR | +- URL "${NGTCP2_URL}" +- URL_HASH "${NGTCP2_URL_HASH}" ++ DOWNLOAD_COMMAND "" + SOURCE_DIR "${DEPS_SRC_DIR}/ngtcp2" + BINARY_DIR "${DEPS_BUILD_DIR}/ngtcp2" + INSTALL_DIR "${DEPS_INSTALL_DIR}" +@@ -473,8 +466,8 @@ + endif() + if(APPLE) + list(APPEND _curl_staged_dependency_args +- "-DCMAKE_IGNORE_PREFIX_PATH=/usr/local|/opt/homebrew" +- "-DCMAKE_IGNORE_PATH=/usr/local/include|/usr/local/lib|/opt/homebrew/include|/opt/homebrew/lib" ++ "-DCMAKE_IGNORE_PREFIX_PATH=@PREFIX@" ++ "-DCMAKE_IGNORE_PATH=@PREFIX@/include|@PREFIX@/lib" + ) + endif() + if(USE_LIBIDN2 AND NOT WIN32) +@@ -497,8 +490,6 @@ + else() + list(APPEND _curl_platform_flags "-Dssize_t=long") + endif() +-elseif(APPLE) +- list(APPEND _curl_platform_flags -DUSE_APPLE_SECTRUST=ON) + endif() + if(CMAKE_MSVC_RUNTIME_LIBRARY) + list(APPEND _curl_platform_flags "-DCMAKE_MSVC_RUNTIME_LIBRARY=${CMAKE_MSVC_RUNTIME_LIBRARY}") +@@ -514,6 +505,15 @@ + string(STRIP "${_curl_shared_linker_flags}" _curl_shared_linker_flags) + list(APPEND _curl_platform_flags "-DCMAKE_EXE_LINKER_FLAGS=${_curl_exe_linker_flags}") + list(APPEND _curl_platform_flags "-DCMAKE_SHARED_LINKER_FLAGS=${_curl_shared_linker_flags}") ++elseif(APPLE) ++ set(_curl_exe_linker_flags "${CMAKE_EXE_LINKER_FLAGS}") ++ set(_curl_shared_linker_flags "${CMAKE_SHARED_LINKER_FLAGS}") ++ string(APPEND _curl_exe_linker_flags " -l${CURL_IMPERSONATE_CXX_RUNTIME_LIBRARY}") ++ string(APPEND _curl_shared_linker_flags " -l${CURL_IMPERSONATE_CXX_RUNTIME_LIBRARY}") ++ string(STRIP "${_curl_exe_linker_flags}" _curl_exe_linker_flags) ++ string(STRIP "${_curl_shared_linker_flags}" _curl_shared_linker_flags) ++ list(APPEND _curl_platform_flags "-DCMAKE_EXE_LINKER_FLAGS=${_curl_exe_linker_flags}") ++ list(APPEND _curl_platform_flags "-DCMAKE_SHARED_LINKER_FLAGS=${_curl_shared_linker_flags}") + endif() + + set(_curl_openssl_flags) +@@ -539,8 +539,7 @@ + + ExternalProject_Add(curl + LIST_SEPARATOR | +- URL "${CURL_URL}" +- URL_HASH "${CURL_URL_HASH}" ++ DOWNLOAD_COMMAND "" + SOURCE_DIR "${DEPS_SRC_DIR}/curl" + BINARY_DIR "${DEPS_BUILD_DIR}/curl" + INSTALL_DIR "${CMAKE_INSTALL_PREFIX}" diff --git a/net/curl-impersonate/files/0002-libiconv.patch b/net/curl-impersonate/files/0002-libiconv.patch new file mode 100644 index 0000000000000..798b5d916785b --- /dev/null +++ b/net/curl-impersonate/files/0002-libiconv.patch @@ -0,0 +1,39 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 8dafe03..eae4ce1 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -478,10 +478,32 @@ if(APPLE) + ) + endif() + if(USE_LIBIDN2 AND NOT WIN32) +- # The prebuild makes libidn2 self-contained with its included libunistring. ++ # The prebuild makes libidn2 self-contained with its included libunistring, ++ # except for iconv: libunistring's striconveh.c calls the plain POSIX ++ # iconv()/iconv_open()/iconv_close() symbols, which are not part of ++ # a static archive's own link requirements, so they must be supplied again ++ # here when libidn2.a gets linked into curl. On Apple platforms iconv is ++ # not part of libSystem's implicit re-exports (unlike on glibc) and always ++ # needs to be linked explicitly; pinning the absolute path to Apple's ++ # /usr/lib/libiconv.dylib (rather than a bare -liconv) guarantees this ++ # resolves to the system copy even when a package manager's own libiconv ++ # is reachable on the linker search path. ++ # ++ # LIBIDN2_LIBRARY must carry both paths as one CMake list value (curl's ++ # FindLibidn2.cmake forwards it verbatim into an INTERFACE_LINK_LIBRARIES ++ # property). This ExternalProject_Add(curl ...) call's CONFIGURE_COMMAND ++ # is a plain command list, so a literal ";" here would already be split ++ # into separate command-line words by CMake's own configure-time list ++ # handling before it ever reaches the nested cmake invocation - use the ++ # same LIST_SEPARATOR token ("|", declared below) already used for ++ # CMAKE_IGNORE_PREFIX_PATH/CMAKE_IGNORE_PATH above for the same reason. ++ set(_libidn2_link_libs "${DEPS_INSTALL_DIR}/lib/libidn2.a") ++ if(APPLE) ++ string(APPEND _libidn2_link_libs "|@ICONV_PREFIX@/lib/libiconv.dylib") ++ endif() + list(APPEND _curl_staged_dependency_args + "-DLIBIDN2_INCLUDE_DIR=${DEPS_INSTALL_DIR}/include" +- "-DLIBIDN2_LIBRARY=${DEPS_INSTALL_DIR}/lib/libidn2.a" ++ "-DLIBIDN2_LIBRARY=${_libidn2_link_libs}" + ) + endif() + diff --git a/net/curl-impersonate/files/0003-boringssl.patch b/net/curl-impersonate/files/0003-boringssl.patch new file mode 100644 index 0000000000000..ba60c8860ced5 --- /dev/null +++ b/net/curl-impersonate/files/0003-boringssl.patch @@ -0,0 +1,828 @@ +From 34d88b786662d1636a63d5cac22f728f19f80055 Mon Sep 17 00:00:00 2001 +From: Sergey Fedorov +Date: Tue, 4 Aug 2026 08:58:18 +0000 +Subject: [PATCH] Fix big-endian + + crypto/blake2/blake2.cc | 8 +++ + crypto/bytestring/cbb.cc | 12 +++++ + crypto/chacha/chacha.cc | 29 ++++++++-- + crypto/compiler_test.cc | 6 ++- + crypto/curve25519/spake25519.cc | 17 ++++++ + crypto/ec/hash_to_curve.cc | 6 +++ + crypto/evp/scrypt.cc | 20 +++++++ + crypto/fipsmodule/aes/aes_nohw.cc.inc | 40 ++++++++++++++ + crypto/fipsmodule/bn/bytes.cc.inc | 38 ++++++++++++-- + crypto/fipsmodule/entropy/sha512.cc.inc | 8 +++ + crypto/fipsmodule/keccak/keccak.cc.inc | 70 +++++++++++++------------ + crypto/internal.h | 62 ++++++++++++++++++++++ + crypto/siphash/siphash_test.cc | 12 +++++ + include/openssl/target.h | 11 ++++ + 14 files changed, 296 insertions(+), 43 deletions(-) + +diff --git a/crypto/blake2/blake2.cc b/crypto/blake2/blake2.cc +index a14cb8e..ce5d9a6 100644 +--- a/deps/src/boringssl/crypto/blake2/blake2.cc ++++ b/deps/src/boringssl/crypto/blake2/blake2.cc +@@ -161,7 +161,15 @@ void BLAKE2B256_Final(uint8_t out[BLAKE2B256_DIGEST_LENGTH], BLAKE2B_CTX *b2b) { + blake2b_transform(b2b, b2b->block, b2b->block_used, + /*is_final_block=*/1); + static_assert(BLAKE2B256_DIGEST_LENGTH <= sizeof(b2b->h)); ++#ifdef OPENSSL_BIGENDIAN ++ uint64_t hswap[BLAKE2B256_DIGEST_LENGTH / sizeof(uint64_t)]; ++ for (size_t i = 0; i < BLAKE2B256_DIGEST_LENGTH / sizeof(uint64_t); i++) { ++ hswap[i] = CRYPTO_bswap8(b2b->h[i]); ++ } ++ memcpy(out, hswap, BLAKE2B256_DIGEST_LENGTH); ++#else + memcpy(out, b2b->h, BLAKE2B256_DIGEST_LENGTH); ++#endif + } + + void BLAKE2B256(const uint8_t *data, size_t len, +diff --git a/crypto/bytestring/cbb.cc b/crypto/bytestring/cbb.cc +index 9400ab9..13258bb 100644 +--- a/deps/src/boringssl/crypto/bytestring/cbb.cc ++++ b/deps/src/boringssl/crypto/bytestring/cbb.cc +@@ -571,17 +571,29 @@ int CBB_add_asn1_int64_with_tag(CBB *cbb, int64_t value, CBS_ASN1_TAG tag) { + + uint8_t bytes[sizeof(int64_t)]; + memcpy(bytes, &value, sizeof(value)); ++#ifdef OPENSSL_BIGENDIAN ++ int start = 0; ++ // Skip leading sign-extension bytes unless they are necessary. ++ while (start < 7 && (bytes[start] == 0xff && (bytes[start + 1] & 0x80))) { ++ start++; ++ } ++#else + int start = 7; + // Skip leading sign-extension bytes unless they are necessary. + while (start > 0 && (bytes[start] == 0xff && (bytes[start - 1] & 0x80))) { + start--; + } ++#endif + + CBB child; + if (!CBB_add_asn1(cbb, &child, tag)) { + goto err; + } ++#ifdef OPENSSL_BIGENDIAN ++ for (int i = start; i <= 7; i++) { ++#else + for (int i = start; i >= 0; i--) { ++#endif + if (!CBB_add_u8(&child, bytes[i])) { + goto err; + } +diff --git a/crypto/chacha/chacha.cc b/crypto/chacha/chacha.cc +index 808a975..bf3382c 100644 +--- a/deps/src/boringssl/crypto/chacha/chacha.cc ++++ b/deps/src/boringssl/crypto/chacha/chacha.cc +@@ -43,9 +43,26 @@ static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', + void bssl::CRYPTO_hchacha20(uint8_t out[32], const uint8_t key[32], + const uint8_t nonce[16]) { + uint32_t x[16]; +- OPENSSL_memcpy(x, sigma, sizeof(sigma)); +- OPENSSL_memcpy(&x[4], key, 32); +- OPENSSL_memcpy(&x[12], nonce, 16); ++ ++ x[0] = CRYPTO_load_u32_le(sigma + 0); ++ x[1] = CRYPTO_load_u32_le(sigma + 4); ++ x[2] = CRYPTO_load_u32_le(sigma + 8); ++ x[3] = CRYPTO_load_u32_le(sigma + 12); ++ ++ x[4] = CRYPTO_load_u32_le(key + 0); ++ x[5] = CRYPTO_load_u32_le(key + 4); ++ x[6] = CRYPTO_load_u32_le(key + 8); ++ x[7] = CRYPTO_load_u32_le(key + 12); ++ ++ x[8] = CRYPTO_load_u32_le(key + 16); ++ x[9] = CRYPTO_load_u32_le(key + 20); ++ x[10] = CRYPTO_load_u32_le(key + 24); ++ x[11] = CRYPTO_load_u32_le(key + 28); ++ ++ x[12] = CRYPTO_load_u32_le(nonce + 0); ++ x[13] = CRYPTO_load_u32_le(nonce + 4); ++ x[14] = CRYPTO_load_u32_le(nonce + 8); ++ x[15] = CRYPTO_load_u32_le(nonce + 12); + + for (size_t i = 0; i < 20; i += 2) { + QUARTERROUND(0, 4, 8, 12) +@@ -58,8 +75,10 @@ void bssl::CRYPTO_hchacha20(uint8_t out[32], const uint8_t key[32], + QUARTERROUND(3, 4, 9, 14) + } + +- OPENSSL_memcpy(out, &x[0], sizeof(uint32_t) * 4); +- OPENSSL_memcpy(&out[16], &x[12], sizeof(uint32_t) * 4); ++ for (size_t i = 0; i < 4; ++i) { ++ CRYPTO_store_u32_le(out + 4 * i, x[i]); ++ CRYPTO_store_u32_le(&out[16] + 4 * i, x[12 + i]); ++ } + } + + #if defined(CHACHA20_ASM_NOHW) +diff --git a/crypto/compiler_test.cc b/crypto/compiler_test.cc +index 58c926d..cdf5983 100644 +--- a/deps/src/boringssl/crypto/compiler_test.cc ++++ b/deps/src/boringssl/crypto/compiler_test.cc +@@ -69,9 +69,13 @@ static void CheckRepresentation(T value) { + UnsignedT value_u = static_cast(value); + EXPECT_EQ(sizeof(UnsignedT), sizeof(T)); + +- // Integers must be little-endian. ++ // Integers must be either big-endian or little-endian. + uint8_t expected[sizeof(UnsignedT)]; ++#ifdef OPENSSL_BIGENDIAN ++ for (size_t i = sizeof(UnsignedT); i-- > 0;) { ++#else + for (size_t i = 0; i < sizeof(UnsignedT); i++) { ++#endif + expected[i] = static_cast(value_u); + // Divide instead of right-shift to appease compilers that warn if `T` is a + // char. The explicit cast is also needed to appease MSVC if integer +diff --git a/crypto/curve25519/spake25519.cc b/crypto/curve25519/spake25519.cc +index ee5cd7c..d06fde5 100644 +--- a/deps/src/boringssl/crypto/curve25519/spake25519.cc ++++ b/deps/src/boringssl/crypto/curve25519/spake25519.cc +@@ -393,7 +393,16 @@ int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, size_t *out_len, + // bit and so one for all the bottom three bits. + + scalar password_scalar; ++#ifdef OPENSSL_BIGENDIAN ++ // `password_tmp` is a little-endian byte string; convert it to words, ++ // adjusting for the byte order within each word with the XOR pattern. ++ uint8_t *pws = (uint8_t *)&password_scalar; ++ for (size_t i = 0; i < sizeof(password_scalar); i++) { ++ pws[i ^ (sizeof(BN_ULONG) - 1)] = password_tmp[i]; ++ } ++#else + OPENSSL_memcpy(&password_scalar, password_tmp, sizeof(password_scalar)); ++#endif + + // `password_scalar` is the result of `x25519_sc_reduce` and thus is, at + // most, $l-1$ (where $l$ is `kOrder`, the order of the prime-order subgroup +@@ -424,8 +433,16 @@ int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, size_t *out_len, + assert((password_scalar.words[0] & 7) == 0); + } + ++#ifdef OPENSSL_BIGENDIAN ++ // Convert the words back to a little-endian byte string. ++ for (size_t i = 0; i < sizeof(ctx->password_scalar); i++) { ++ ctx->password_scalar[i] = ++ ((uint8_t *)password_scalar.words)[i ^ (sizeof(BN_ULONG) - 1)]; ++ } ++#else + OPENSSL_memcpy(ctx->password_scalar, password_scalar.words, + sizeof(ctx->password_scalar)); ++#endif + + ge_p3 mask; + x25519_ge_scalarmult_small_precomp(&mask, ctx->password_scalar, +diff --git a/crypto/ec/hash_to_curve.cc b/crypto/ec/hash_to_curve.cc +index 8fae618..2ee9912 100644 +--- a/deps/src/boringssl/crypto/ec/hash_to_curve.cc ++++ b/deps/src/boringssl/crypto/ec/hash_to_curve.cc +@@ -163,7 +163,13 @@ void big_endian_to_words(Span out, Span in) { + OPENSSL_memset(out.data(), 0, out.size() * sizeof(BN_ULONG)); + uint8_t *out_u8 = reinterpret_cast(out.data()); + for (size_t i = 0; i < in.size(); i++) { ++#ifdef OPENSSL_BIGENDIAN ++ // On big-endian, adjust for the byte order within each word with the XOR ++ // pattern. ++ out_u8[(in.size() - 1 - i) ^ (sizeof(BN_ULONG) - 1)] = in[i]; ++#else + out_u8[in.size() - 1 - i] = in[i]; ++#endif + } + } + +diff --git a/crypto/evp/scrypt.cc b/crypto/evp/scrypt.cc +index d1e89a7..40dce20 100644 +--- a/deps/src/boringssl/crypto/evp/scrypt.cc ++++ b/deps/src/boringssl/crypto/evp/scrypt.cc +@@ -201,10 +201,30 @@ int EVP_PBE_scrypt(const char *password, size_t password_len, + goto err; + } + ++#ifdef OPENSSL_BIGENDIAN ++ // The PBKDF2 output is interpreted as a sequence of little-endian words, so ++ // byte-swap into the host representation. ++ for (size_t i = 0; i < B_blocks; i++) { ++ for (size_t j = 0; j < 16; j++) { ++ B[i].words[j] = CRYPTO_bswap4(B[i].words[j]); ++ } ++ } ++#endif ++ + for (uint64_t i = 0; i < p; i++) { + scryptROMix(B + 2 * r * i, r, N, T, V); + } + ++#ifdef OPENSSL_BIGENDIAN ++ // Byte-swap back so the following PBKDF2 hashes the little-endian ++ // serialization. ++ for (size_t i = 0; i < B_blocks; i++) { ++ for (size_t j = 0; j < 16; j++) { ++ B[i].words[j] = CRYPTO_bswap4(B[i].words[j]); ++ } ++ } ++#endif ++ + if (!PKCS5_PBKDF2_HMAC(password, password_len, (const uint8_t *)B, B_bytes, 1, + EVP_sha256(), key_len, out_key)) { + goto err; +diff --git a/crypto/fipsmodule/aes/aes_nohw.cc.inc b/crypto/fipsmodule/aes/aes_nohw.cc.inc +index 0c31251..ea34868 100644 +--- a/deps/src/boringssl/crypto/fipsmodule/aes/aes_nohw.cc.inc ++++ b/deps/src/boringssl/crypto/fipsmodule/aes/aes_nohw.cc.inc +@@ -284,6 +284,26 @@ static aes_word_t aes_nohw_delta_swap(aes_word_t a, aes_word_t mask, + // http://programming.sirrida.de/calcperm.php on smaller inputs. + #if defined(OPENSSL_64_BIT) + static uint64_t aes_nohw_compact_word(uint64_t a) { ++#ifdef OPENSSL_BIGENDIAN ++ // On big-endian the 16 4-bit chunks are numbered MSB-first, so the ++ // permutation steps are reversed relative to the LE case. ++ // Swap pairs of 4-bit chunks: ++ // 14 15 12 13 | 10 11 8 9 | 6 7 4 5 | 2 3 0 1 => ++ // 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 ++ a = aes_nohw_delta_swap(a, UINT64_C(0x0f0f0f0f0f0f0f0f), 4); ++ // Swap quartets of 4-bit chunks: ++ // 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 => ++ // 12 14 13 15 | 8 10 9 11 | 4 6 5 7 | 0 2 1 3 ++ a = aes_nohw_delta_swap(a, UINT64_C(0x000f000f000f000f), 12); ++ // Swap quartets of 8-bit chunks: ++ // 12 14 13 15 | 8 10 9 11 | 4 6 5 7 | 0 2 1 3 => ++ // 9 11 13 15 | 8 10 12 14 | 1 3 5 7 | 0 2 4 6 ++ a = aes_nohw_delta_swap(a, UINT64_C(0x000000ff000000ff), 24); ++ // Swap quartets of 16-bit chunks: ++ // 9 11 13 15 | 8 10 12 14 | 1 3 5 7 | 0 2 4 6 => ++ // 0 2 4 6 | 8 10 12 14 | 1 3 5 7 | 9 11 13 15 ++ a = aes_nohw_delta_swap(a, UINT64_C(0x000000000000ffff), 48); ++#else + // Numbering the 64/2 = 16 4-bit chunks, least to most significant, we swap + // quartets of those chunks: + // 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | 12 13 14 15 => +@@ -297,18 +317,33 @@ static uint64_t aes_nohw_compact_word(uint64_t a) { + // 0 2 4 6 | 1 3 5 7 | 8 10 12 14 | 9 11 13 15 => + // 0 2 4 6 | 8 10 12 14 | 1 3 5 7 | 9 11 13 15 + a = aes_nohw_delta_swap(a, UINT64_C(0x00000000ffff0000), 16); ++#endif + return a; + } + + static uint64_t aes_nohw_uncompact_word(uint64_t a) { + // Reverse the steps of `aes_nohw_uncompact_word`. ++#ifdef OPENSSL_BIGENDIAN ++ a = aes_nohw_delta_swap(a, UINT64_C(0x000000000000ffff), 48); ++ a = aes_nohw_delta_swap(a, UINT64_C(0x000000ff000000ff), 24); ++ a = aes_nohw_delta_swap(a, UINT64_C(0x000f000f000f000f), 12); ++ a = aes_nohw_delta_swap(a, UINT64_C(0x0f0f0f0f0f0f0f0f), 4); ++#else + a = aes_nohw_delta_swap(a, UINT64_C(0x00000000ffff0000), 16); + a = aes_nohw_delta_swap(a, UINT64_C(0x0000ff000000ff00), 8); + a = aes_nohw_delta_swap(a, UINT64_C(0x00f000f000f000f0), 4); ++#endif + return a; + } + #else // !OPENSSL_64_BIT + static uint32_t aes_nohw_compact_word(uint32_t a) { ++#ifdef OPENSSL_BIGENDIAN ++ // On big-endian, byte 0 of the AES block lands in the MSB of the word. ++ // Byte-swap to LE so the LE delta-swap masks work correctly. The result ++ // is consumed byte-by-byte via aes_nohw_word_from_bytes, so no ++ // second bswap is needed. ++ a = CRYPTO_bswap4(a); ++#endif + // Numbering the 32/2 = 16 pairs of bits, least to most significant, we swap: + // 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | 12 13 14 15 => + // 0 4 2 6 | 1 5 3 7 | 8 12 10 14 | 9 13 11 15 +@@ -327,6 +362,11 @@ static uint32_t aes_nohw_uncompact_word(uint32_t a) { + // Reverse the steps of `aes_nohw_uncompact_word`. + a = aes_nohw_delta_swap(a, 0x0000f0f0, 12); + a = aes_nohw_delta_swap(a, 0x00cc00cc, 6); ++#ifdef OPENSSL_BIGENDIAN ++ // Restore BE byte order so that memcpy(out, &word, 4) writes ++ // AES byte 0 first (into out[0]). ++ a = CRYPTO_bswap4(a); ++#endif + return a; + } + +diff --git a/crypto/fipsmodule/bn/bytes.cc.inc b/crypto/fipsmodule/bn/bytes.cc.inc +index ef2c87b..648f6d1 100644 +--- a/deps/src/boringssl/crypto/fipsmodule/bn/bytes.cc.inc ++++ b/deps/src/boringssl/crypto/fipsmodule/bn/bytes.cc.inc +@@ -111,9 +111,17 @@ BIGNUM *BN_lebin2bn(const uint8_t *in, size_t len, BIGNUM *ret) { + // Make sure the top bytes will be zeroed. + ret->d[num_words - 1] = 0; + ++#ifdef OPENSSL_BIGENDIAN ++ // On big-endian, byte-swap the input data into the internal representation. ++ uint8_t *out = (uint8_t *)ret->d; ++ for (size_t i = 0; i < len; i++) { ++ out[i ^ (BN_BYTES - 1)] = in[i]; ++ } ++#else + // We only support little-endian platforms, so we can simply memcpy the + // internal representation. + OPENSSL_memcpy(ret->d, in, len); ++#endif + return ret; + } + +@@ -129,7 +137,11 @@ static int fits_in_bytes(const BN_ULONG *words, size_t num_words, + size_t tot_bytes = num_words * sizeof(BN_ULONG); + uint8_t mask = 0; + for (size_t i = num_bytes; i < tot_bytes; i++) { ++#ifdef OPENSSL_BIGENDIAN ++ mask |= bytes[i ^ (BN_BYTES - 1)]; ++#else + mask |= bytes[i]; ++#endif + } + return mask == 0; + } +@@ -140,7 +152,11 @@ void bssl::bn_assert_fits_in_bytes(const BIGNUM *bn, size_t num) { + if (tot_bytes > num) { + CONSTTIME_DECLASSIFY(bytes + num, tot_bytes - num); + for (size_t i = num; i < tot_bytes; i++) { ++#ifdef OPENSSL_BIGENDIAN ++ assert(bytes[i ^ (BN_BYTES - 1)] == 0); ++#else + assert(bytes[i] == 0); ++#endif + } + (void)bytes; + } +@@ -151,17 +167,24 @@ void bssl::bn_words_to_big_endian(uint8_t *out, size_t out_len, + // The caller should have selected an output length without truncation. + declassify_assert(fits_in_bytes(in, in_len, out_len)); + +- // We only support little-endian platforms, so the internal representation is +- // also little-endian as bytes. We can simply copy it in reverse. + const uint8_t *bytes = (const uint8_t *)in; + size_t num_bytes = in_len * sizeof(BN_ULONG); + if (out_len < num_bytes) { + num_bytes = out_len; + } + ++#ifdef OPENSSL_BIGENDIAN ++ // On big-endian, internal representation is big-endian, so swap index. ++ for (size_t i = 0; i < num_bytes; i++) { ++ out[out_len - i - 1] = bytes[i ^ (BN_BYTES - 1)]; ++ } ++#else ++ // We only support little-endian platforms, so the internal representation is ++ // also little-endian as bytes. We can simply copy it in reverse. + for (size_t i = 0; i < num_bytes; i++) { + out[out_len - i - 1] = bytes[i]; + } ++#endif + // Pad out the rest of the buffer with zeroes. + OPENSSL_memset(out, 0, out_len - num_bytes); + } +@@ -177,15 +200,22 @@ int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in) { + return 0; + } + +- // We only support little-endian platforms, so we can simply memcpy into the +- // internal representation. + const uint8_t *bytes = (const uint8_t *)in->d; + size_t num_bytes = in->width * BN_BYTES; + if (len < num_bytes) { + num_bytes = len; + } + ++#ifdef OPENSSL_BIGENDIAN ++ // On big-endian, byte-swap the internal representation to little-endian output. ++ for (size_t i = 0; i < num_bytes; i++) { ++ out[i] = bytes[i ^ (BN_BYTES - 1)]; ++ } ++#else ++ // We only support little-endian platforms, so we can simply memcpy into the ++ // internal representation. + OPENSSL_memcpy(out, bytes, num_bytes); ++#endif + // Pad out the rest of the buffer with zeroes. + OPENSSL_memset(out + num_bytes, 0, len - num_bytes); + return 1; +diff --git a/crypto/fipsmodule/entropy/sha512.cc.inc b/crypto/fipsmodule/entropy/sha512.cc.inc +index 1d954d0..65f5644 100644 +--- a/deps/src/boringssl/crypto/fipsmodule/entropy/sha512.cc.inc ++++ b/deps/src/boringssl/crypto/fipsmodule/entropy/sha512.cc.inc +@@ -36,16 +36,24 @@ struct SHA512_CTX { + unsigned num, md_len; + }; + ++#ifndef OPENSSL_BIGENDIAN + uint64_t CRYPTO_bswap8(uint64_t x) { return __builtin_bswap64(x); } ++#endif + + uint64_t CRYPTO_load_u64_be(const void *ptr) { + uint64_t ret; + memcpy(&ret, ptr, sizeof(ret)); ++#ifdef OPENSSL_BIGENDIAN ++ return ret; ++#else + return CRYPTO_bswap8(ret); ++#endif + } + + void CRYPTO_store_u64_be(void *out, uint64_t v) { ++#ifndef OPENSSL_BIGENDIAN + v = CRYPTO_bswap8(v); ++#endif + memcpy(out, &v, sizeof(v)); + } + +diff --git a/crypto/fipsmodule/keccak/keccak.cc.inc b/crypto/fipsmodule/keccak/keccak.cc.inc +index 83b8647..6d4753a 100644 +--- a/deps/src/boringssl/crypto/fipsmodule/keccak/keccak.cc.inc ++++ b/deps/src/boringssl/crypto/fipsmodule/keccak/keccak.cc.inc +@@ -292,16 +292,15 @@ void bssl::BORINGSSL_keccak_absorb(struct BORINGSSL_keccak_st *ctx, + BSSL_CHECK(ctx->phase != boringssl_keccak_phase_squeeze); + + const size_t rate_words = ctx->rate_bytes / 8; +- // XOR the input. Accessing `ctx->state` as a `uint8_t*` is allowed by +- // strict aliasing because we require `uint8_t` to be a character type. +- uint8_t *state_bytes = (uint8_t *)ctx->state; + +- // Absorb partial block. ++ // Absorb partial block. XOR the input into the correct little-endian byte ++ // position within each lane, which is endianness-independent. + if (ctx->absorb_offset != 0) { + assert(ctx->absorb_offset < ctx->rate_bytes); + size_t first_block_len = ctx->rate_bytes - ctx->absorb_offset; + for (size_t i = 0; i < first_block_len && i < in_len; i++) { +- state_bytes[ctx->absorb_offset + i] ^= in[i]; ++ size_t byte_pos = ctx->absorb_offset + i; ++ ctx->state[byte_pos / 8] ^= (uint64_t)in[i] << (8 * (byte_pos % 8)); + } + + // This input didn't fill the block. +@@ -328,7 +327,7 @@ void bssl::BORINGSSL_keccak_absorb(struct BORINGSSL_keccak_st *ctx, + // Absorb partial block. + assert(in_len < ctx->rate_bytes); + for (size_t i = 0; i < in_len; i++) { +- state_bytes[i] ^= in[i]; ++ ctx->state[i / 8] ^= (uint64_t)in[i] << (8 * (i % 8)); + } + ctx->absorb_offset = in_len; + } +@@ -347,22 +346,26 @@ static uint8_t keccak_terminator(struct BORINGSSL_keccak_st *ctx) { + } + + static void keccak_finalize(struct BORINGSSL_keccak_st *ctx) { +- // XOR the terminator. Accessing `ctx->state` as a `uint8_t*` is allowed by +- // strict aliasing because we require `uint8_t` to be a character type. +- uint8_t *state_bytes = (uint8_t *)ctx->state; +- state_bytes[ctx->absorb_offset] ^= keccak_terminator(ctx); +- state_bytes[ctx->rate_bytes - 1] ^= 0x80; ++ // XOR the terminator into the correct little-endian byte position within ++ // the lane, which is endianness-independent. ++ uint8_t terminator = keccak_terminator(ctx); ++ ctx->state[ctx->absorb_offset / 8] ^= ++ (uint64_t)terminator << (8 * (ctx->absorb_offset % 8)); ++ ctx->state[(ctx->rate_bytes - 1) / 8] ^= ++ (uint64_t)0x80 << (8 * ((ctx->rate_bytes - 1) % 8)); + keccak_f(ctx->state); + } + + #if defined(HAVE_KECCAK_X2) + static void keccak_finalize_x2(struct BORINGSSL_keccak_st ctx[2]) { + for (size_t i = 0; i < 2; ++i) { +- // XOR the terminator. Accessing `ctx->state` as a `uint8_t*` is allowed +- // by strict aliasing because we require `uint8_t` to be a character type. +- uint8_t *state_bytes = (uint8_t *)ctx[i].state; +- state_bytes[ctx[i].absorb_offset] ^= keccak_terminator(&ctx[i]); +- state_bytes[ctx[i].rate_bytes - 1] ^= 0x80; ++ // XOR the terminator into the correct little-endian byte position within ++ // the lane, which is endianness-independent. ++ uint8_t terminator = keccak_terminator(&ctx[i]); ++ ctx[i].state[ctx[i].absorb_offset / 8] ^= ++ (uint64_t)terminator << (8 * (ctx[i].absorb_offset % 8)); ++ ctx[i].state[(ctx[i].rate_bytes - 1) / 8] ^= ++ (uint64_t)0x80 << (8 * ((ctx[i].rate_bytes - 1) % 8)); + } + keccak_f_x2(ctx[0].state, ctx[1].state); + } +@@ -371,8 +374,6 @@ static void keccak_finalize_x2(struct BORINGSSL_keccak_st ctx[2]) { + #if defined(HAVE_KECCAK_X4) + static void keccak_finalize_x4(struct BORINGSSL_keccak_st ctx[4]) { + for (size_t i = 0; i < 4; ++i) { +- // XOR the terminator. Accessing `ctx->state` as a `uint8_t*` is allowed +- // by strict aliasing because we require `uint8_t` to be a character type. + uint8_t terminator; + switch (ctx[i].config) { + case boringssl_sha3_256: +@@ -386,9 +387,12 @@ static void keccak_finalize_x4(struct BORINGSSL_keccak_st ctx[4]) { + default: + abort(); + } +- uint8_t *state_bytes = (uint8_t *)ctx[i].state; +- state_bytes[ctx[i].absorb_offset] ^= terminator; +- state_bytes[ctx[i].rate_bytes - 1] ^= 0x80; ++ // XOR the terminator into the correct little-endian byte position within ++ // the lane, which is endianness-independent. ++ ctx[i].state[ctx[i].absorb_offset / 8] ^= ++ (uint64_t)terminator << (8 * (ctx[i].absorb_offset % 8)); ++ ctx[i].state[(ctx[i].rate_bytes - 1) / 8] ^= ++ (uint64_t)0x80 << (8 * ((ctx[i].rate_bytes - 1) % 8)); + } + keccak_f_x4(ctx[0].state, ctx[1].state, ctx[2].state, ctx[3].state); + } +@@ -407,9 +411,6 @@ void bssl::BORINGSSL_keccak_squeeze(struct BORINGSSL_keccak_st *ctx, + ctx->phase = boringssl_keccak_phase_squeeze; + } + +- // Accessing `ctx->state` as a `uint8_t*` is allowed by strict aliasing +- // because we require `uint8_t` to be a character type. +- const uint8_t *state_bytes = (const uint8_t *)ctx->state; + while (out_len) { + if (ctx->squeeze_offset == ctx->rate_bytes) { + keccak_f(ctx->state); +@@ -421,7 +422,10 @@ void bssl::BORINGSSL_keccak_squeeze(struct BORINGSSL_keccak_st *ctx, + if (todo > remaining) { + todo = remaining; + } +- OPENSSL_memcpy(out, &state_bytes[ctx->squeeze_offset], todo); ++ for (size_t i = 0; i < todo; i++) { ++ size_t byte_pos = ctx->squeeze_offset + i; ++ out[i] = (ctx->state[byte_pos / 8] >> (8 * (byte_pos % 8))) & 0xff; ++ } + out += todo; + out_len -= todo; + ctx->squeeze_offset += todo; +@@ -457,8 +461,6 @@ void bssl::BORINGSSL_keccak_squeeze_x2(struct BORINGSSL_keccak_st ctx[2], + ctx->phase = boringssl_keccak_phase_squeeze; + } + +- // Accessing `ctx->state` as a `uint8_t*` is allowed by strict aliasing +- // because we require `uint8_t` to be a character type. + uint8_t *optr[2] = {outs[0], outs[1]}; + while (out_len) { + if (ctx->squeeze_offset == ctx->rate_bytes) { +@@ -472,8 +474,10 @@ void bssl::BORINGSSL_keccak_squeeze_x2(struct BORINGSSL_keccak_st ctx[2], + todo = remaining; + } + for (size_t i = 0; i < 2; ++i) { +- const uint8_t *state_bytes = (const uint8_t *)ctx[i].state; +- OPENSSL_memcpy(optr[i], &state_bytes[ctx->squeeze_offset], todo); ++ for (size_t j = 0; j < todo; j++) { ++ size_t byte_pos = ctx->squeeze_offset + j; ++ optr[i][j] = (ctx[i].state[byte_pos / 8] >> (8 * (byte_pos % 8))) & 0xff; ++ } + optr[i] += todo; + } + out_len -= todo; +@@ -520,8 +524,6 @@ KECCAK_X4_TARGET void bssl::BORINGSSL_keccak_squeeze_x4( + ctx->phase = boringssl_keccak_phase_squeeze; + } + +- // Accessing `ctx->state` as a `uint8_t*` is allowed by strict aliasing +- // because we require `uint8_t` to be a character type. + uint8_t *optr[4] = {outs[0], outs[1], outs[2], outs[3]}; + while (out_len) { + if (ctx->squeeze_offset == ctx->rate_bytes) { +@@ -535,8 +537,10 @@ KECCAK_X4_TARGET void bssl::BORINGSSL_keccak_squeeze_x4( + todo = remaining; + } + for (size_t i = 0; i < 4; ++i) { +- const uint8_t *state_bytes = (const uint8_t *)ctx[i].state; +- OPENSSL_memcpy(optr[i], &state_bytes[ctx->squeeze_offset], todo); ++ for (size_t j = 0; j < todo; j++) { ++ size_t byte_pos = ctx->squeeze_offset + j; ++ optr[i][j] = (ctx[i].state[byte_pos / 8] >> (8 * (byte_pos % 8))) & 0xff; ++ } + optr[i] += todo; + } + out_len -= todo; +diff --git a/crypto/internal.h b/crypto/internal.h +index dda1933..5533804 100644 +--- a/deps/src/boringssl/crypto/internal.h ++++ b/deps/src/boringssl/crypto/internal.h +@@ -903,79 +903,140 @@ inline void *OPENSSL_memset(void *dst, int c, size_t n) { + inline uint16_t CRYPTO_load_u16_le(const void *in) { + uint16_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); ++#ifdef OPENSSL_BIGENDIAN ++ return CRYPTO_bswap2(v); ++#else + return v; ++#endif + } + + inline void CRYPTO_store_u16_le(void *out, uint16_t v) { ++#ifdef OPENSSL_BIGENDIAN ++ v = CRYPTO_bswap2(v); ++#endif + OPENSSL_memcpy(out, &v, sizeof(v)); + } + + inline uint16_t CRYPTO_load_u16_be(const void *in) { + uint16_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); ++#ifdef OPENSSL_BIGENDIAN ++ return v; ++#else + return CRYPTO_bswap2(v); ++#endif + } + + inline void CRYPTO_store_u16_be(void *out, uint16_t v) { ++#ifndef OPENSSL_BIGENDIAN + v = CRYPTO_bswap2(v); ++#endif + OPENSSL_memcpy(out, &v, sizeof(v)); + } + + inline uint32_t CRYPTO_load_u32_le(const void *in) { + uint32_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); ++#ifdef OPENSSL_BIGENDIAN ++ return CRYPTO_bswap4(v); ++#else + return v; ++#endif + } + + inline void CRYPTO_store_u32_le(void *out, uint32_t v) { ++#ifdef OPENSSL_BIGENDIAN ++ v = CRYPTO_bswap4(v); ++#endif + OPENSSL_memcpy(out, &v, sizeof(v)); + } + + inline uint32_t CRYPTO_load_u32_be(const void *in) { + uint32_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); ++#ifdef OPENSSL_BIGENDIAN ++ return v; ++#else + return CRYPTO_bswap4(v); ++#endif + } + + inline void CRYPTO_store_u32_be(void *out, uint32_t v) { ++#ifndef OPENSSL_BIGENDIAN + v = CRYPTO_bswap4(v); ++#endif + OPENSSL_memcpy(out, &v, sizeof(v)); + } + + inline uint64_t CRYPTO_load_u64_le(const void *in) { + uint64_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); ++#ifdef OPENSSL_BIGENDIAN ++ return CRYPTO_bswap8(v); ++#else + return v; ++#endif + } + + inline void CRYPTO_store_u64_le(void *out, uint64_t v) { ++#ifdef OPENSSL_BIGENDIAN ++ v = CRYPTO_bswap8(v); ++#endif + OPENSSL_memcpy(out, &v, sizeof(v)); + } + + inline uint64_t CRYPTO_load_u64_be(const void *ptr) { + uint64_t ret; + OPENSSL_memcpy(&ret, ptr, sizeof(ret)); ++#ifdef OPENSSL_BIGENDIAN ++ return ret; ++#else + return CRYPTO_bswap8(ret); ++#endif + } + + inline void CRYPTO_store_u64_be(void *out, uint64_t v) { ++#ifndef OPENSSL_BIGENDIAN + v = CRYPTO_bswap8(v); ++#endif + OPENSSL_memcpy(out, &v, sizeof(v)); + } + + inline crypto_word_t CRYPTO_load_word_le(const void *in) { + crypto_word_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); ++#ifdef OPENSSL_BIGENDIAN ++#if defined(OPENSSL_64_BIT) ++ static_assert(sizeof(v) == 8, "crypto_word_t has unexpected size"); ++ return CRYPTO_bswap8(v); ++#else ++ static_assert(sizeof(v) == 4, "crypto_word_t has unexpected size"); ++ return CRYPTO_bswap4(v); ++#endif ++#else + return v; ++#endif + } + + inline void CRYPTO_store_word_le(void *out, crypto_word_t v) { ++#ifdef OPENSSL_BIGENDIAN ++#if defined(OPENSSL_64_BIT) ++ static_assert(sizeof(v) == 8, "crypto_word_t has unexpected size"); ++ v = CRYPTO_bswap8(v); ++#else ++ static_assert(sizeof(v) == 4, "crypto_word_t has unexpected size"); ++ v = CRYPTO_bswap4(v); ++#endif ++#endif + OPENSSL_memcpy(out, &v, sizeof(v)); + } + + inline crypto_word_t CRYPTO_load_word_be(const void *in) { + crypto_word_t v; + OPENSSL_memcpy(&v, in, sizeof(v)); ++#ifdef OPENSSL_BIGENDIAN ++ return v; ++#else + #if defined(OPENSSL_64_BIT) + static_assert(sizeof(v) == 8, "crypto_word_t has unexpected size"); + return CRYPTO_bswap8(v); +@@ -983,6 +1044,7 @@ inline crypto_word_t CRYPTO_load_word_be(const void *in) { + static_assert(sizeof(v) == 4, "crypto_word_t has unexpected size"); + return CRYPTO_bswap4(v); + #endif ++#endif + } + + +diff --git a/crypto/siphash/siphash_test.cc b/crypto/siphash/siphash_test.cc +index 8095bb8..5b3e364 100644 +--- a/deps/src/boringssl/crypto/siphash/siphash_test.cc ++++ b/deps/src/boringssl/crypto/siphash/siphash_test.cc +@@ -14,10 +14,13 @@ + + #include + ++#include ++ + #include + + #include + ++#include "../internal.h" + #include "../test/file_test.h" + #include "../test/test_util.h" + +@@ -29,6 +32,10 @@ TEST(SipHash, Basic) { + } + uint64_t key[2]; + memcpy(key, key_bytes, sizeof(key)); ++#ifdef OPENSSL_BIGENDIAN ++ key[0] = bssl::CRYPTO_bswap8(key[0]); ++ key[1] = bssl::CRYPTO_bswap8(key[1]); ++#endif + + uint8_t input[15]; + for (unsigned i = 0; i < sizeof(input); i++) { +@@ -50,6 +57,11 @@ TEST(SipHash, Vectors) { + + uint64_t key_words[2]; + memcpy(key_words, key.data(), key.size()); ++#ifdef OPENSSL_BIGENDIAN ++ key_words[0] = bssl::CRYPTO_bswap8(key_words[0]); ++ key_words[1] = bssl::CRYPTO_bswap8(key_words[1]); ++ std::reverse(hash.begin(), hash.end()); ++#endif + uint64_t result = SIPHASH_24(key_words, msg.data(), msg.size()); + EXPECT_EQ(Bytes(reinterpret_cast(&result), sizeof(result)), + Bytes(hash)); +diff --git a/include/openssl/target.h b/include/openssl/target.h +index 2372a05..e24fddf 100644 +--- a/deps/src/boringssl/include/openssl/target.h ++++ b/deps/src/boringssl/include/openssl/target.h +@@ -34,6 +34,17 @@ + #elif defined(__ARMEL__) || defined(_M_ARM) + #define OPENSSL_32_BIT + #define OPENSSL_ARM ++#elif defined(__powerpc64__) && defined(__LITTLE_ENDIAN__) ++#define OPENSSL_64_BIT ++#define OPENSSL_PPC64LE ++#elif defined(__ppc64__) || defined(__powerpc64__) ++#define OPENSSL_64_BIT ++#define OPENSSL_PPC64 ++#define OPENSSL_BIGENDIAN ++#elif defined(__ppc__) || defined(__powerpc__) ++#define OPENSSL_32_BIT ++#define OPENSSL_PPC ++#define OPENSSL_BIGENDIAN + #elif defined(__MIPSEL__) && !defined(__LP64__) + #define OPENSSL_32_BIT + #define OPENSSL_MIPS + +--- a/deps/src/boringssl/CMakeLists.txt ++++ b/deps/src/boringssl/CMakeLists.txt 2026-08-05 16:55:31.000000000 +0800 +@@ -121,6 +121,10 @@ + add_definitions(-D_CRT_SECURE_NO_WARNINGS) + endif() + ++if(APPLE) ++ add_definitions(-D__STDC_FORMAT_MACROS) ++endif() ++ + # pthread_rwlock_t on Linux requires a feature flag. We limit this to Linux + # because, on Apple platforms, it instead disables APIs we use. See compat(5) + # and sys/cdefs.h. Reportedly, FreeBSD also breaks when this is set. See diff --git a/net/curl-impersonate/files/0004-zstd.patch b/net/curl-impersonate/files/0004-zstd.patch new file mode 100644 index 0000000000000..79c08aa919e37 --- /dev/null +++ b/net/curl-impersonate/files/0004-zstd.patch @@ -0,0 +1,23 @@ +--- a/deps/src/zstd/doc/educational_decoder/Makefile 2021-12-20 16:49:18.000000000 -0600 ++++ b/deps/src/zstd/doc/educational_decoder/Makefile 2021-12-22 03:35:11.000000000 -0600 +@@ -27,7 +27,7 @@ + CFLAGS += -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ + -Wstrict-aliasing=1 -Wswitch-enum \ + -Wredundant-decls -Wstrict-prototypes -Wundef \ +- -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ ++ -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ + -std=c99 + CFLAGS += $(DEBUGFLAGS) + CFLAGS += $(MOREFLAGS) + +--- a/deps/src/zstd/lib/libzstd.mk 2021-12-20 16:49:18.000000000 -0600 ++++ b/deps/src/zstd/lib/libzstd.mk 2021-12-22 02:41:39.000000000 -0600 +@@ -113,7 +113,7 @@ + DEBUGFLAGS= -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow \ + -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \ + -Wstrict-prototypes -Wundef -Wpointer-arith \ +- -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ ++ -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ + -Wredundant-decls -Wmissing-prototypes -Wc++-compat + CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS) + ASFLAGS += $(DEBUGFLAGS) $(MOREFLAGS) $(CFLAGS) diff --git a/python/py-curl-cffi/Portfile b/python/py-curl-cffi/Portfile index 5d0a394d7b73f..805e055868be6 100644 --- a/python/py-curl-cffi/Portfile +++ b/python/py-curl-cffi/Portfile @@ -6,7 +6,7 @@ PortGroup python 1.0 name py-curl-cffi python.rootname curl_cffi version 0.16.0 -revision 0 +revision 1 license MIT maintainers {mps @Schamschula} openmaintainer @@ -14,53 +14,36 @@ description Python binding for curl-impersonate fork via cffi. long_description {*}${description} homepage https://github.com/lexiforest/curl_cffi -set curl_impersonate_version 2.0.0 +master_sites ${homepage}/releases/download/v${version}/ -master_sites https://github.com/lexiforest/curl_cffi/releases/download/v${version}/:curl-cffi \ - https://github.com/lexiforest/curl-impersonate/releases/download/v${curl_impersonate_version}/:libcurl-impersonate +distname ${python.rootname}-${version} -set cffi_distfile ${python.rootname}-${version}${extract.suffix} -set impersonate_distfile \ - libcurl-impersonate-v${curl_impersonate_version}.${configure.build_arch}-macos${extract.suffix} - -checksums ${cffi_distfile} \ - rmd160 31dbfe700f3d028976b4e3faf248b89f3a3ebd2e \ +checksums rmd160 31dbfe700f3d028976b4e3faf248b89f3a3ebd2e \ sha256 b00b423da8028eb6221e3b63bcd63d681150c07cee8b16000d1f7ea292731895 \ size 238344 -extract.only ${cffi_distfile} -distfiles ${cffi_distfile}:curl-cffi \ - ${impersonate_distfile}:libcurl-impersonate - -supported_archs arm64 x86_64 universal_variant no python.versions 310 311 312 313 314 -# See: https://github.com/lexiforest/curl-impersonate -if {${configure.build_arch} eq "arm64"} { - checksums-append ${impersonate_distfile} \ - rmd160 ad01faa75b3265ec79f663e42937894c1e2c30d8 \ - sha256 f8cc4ee6e4cc942fe6b52d905f8fe03ddebda5ffc428683e3b4e0f613cbfff17 \ - size 13466475 -} elseif {${configure.build_arch} eq "x86_64"} { - checksums-append ${impersonate_distfile} \ - rmd160 45428937579351fa0fe389596560befe74a020f8 \ - sha256 253a3a8d5c37d81d7c5250b971e810c72360dd44326cf3c6bed25a6ff1ee562f \ - size 14145129 -} else { - known_fail yes -} - if {${name} ne ${subport}} { - patchfiles patch-scripts-build.py.diff - - depends_lib-append \ - port:py${python.version}-cffi \ - port:py${python.version}-certifi - - post-extract { - ln -s ${distpath}/${impersonate_distfile} \ - ${worksrcpath}/libcurl-impersonate${extract.suffix} + patchfiles patch-scripts-build.py.diff \ + patch-libs.json \ + macports-curl-impersonate.patch + + post-patch { + reinplace "s|@PREFIX@|${prefix}|g" ${worksrcpath}/scripts/build.py + if {${configure.cxx_stdlib} eq "libc++"} { + reinplace "s|@CXXLIB@|c++|g" ${worksrcpath}/scripts/build.py + } else { + reinplace "s|@CXXLIB@|stdc++|g" ${worksrcpath}/scripts/build.py + } } + + depends_lib-append \ + port:curl-impersonate \ + port:py${python.version}-certifi \ + port:py${python.version}-cffi + depends_run-append \ + port:py${python.version}-rich } diff --git a/python/py-curl-cffi/files/macports-curl-impersonate.patch b/python/py-curl-cffi/files/macports-curl-impersonate.patch new file mode 100644 index 0000000000000..4a048300d49d5 --- /dev/null +++ b/python/py-curl-cffi/files/macports-curl-impersonate.patch @@ -0,0 +1,145 @@ +diff --git a/ffi/shim.h b/ffi/shim.h +index 15106a1..2bc0df9 100644 +--- ffi/shim.h ++++ ffi/shim.h +@@ -2,6 +2,10 @@ + #include + #include + #define CURL_STATICLIB ++#ifdef USE_MACPORTS_CURL ++#include "curl-impersonate/curl.h" ++#else + #include "curl/curl.h" ++#endif + + int _curl_easy_setopt(void* curl, int option, void* param); +diff --git a/scripts/build.py b/scripts/build.py +index 3692dd8..2ad1c39 100644 +--- scripts/build.py ++++ scripts/build.py +@@ -27,12 +27,34 @@ def is_android_env() -> bool: + ) + + ++def detect_macports_curl_impersonate(): ++ """Check if curl-impersonate is installed via MacPorts.""" ++ macports_lib = Path("@PREFIX@/lib/libcurl-impersonate.dylib") ++ macports_include = Path("@PREFIX@/include/curl-impersonate") ++ ++ # Check if USE_SYSTEM_CURL_IMPERSONATE env var is set ++ if os.environ.get("USE_SYSTEM_CURL_IMPERSONATE"): ++ return True ++ ++ # Auto-detect MacPorts installation ++ if macports_lib.exists() and macports_include.exists(): ++ return True ++ ++ return False ++ ++def normalize_machine(machine: str) -> str: ++ m = machine.lower() ++ if m in {"power", "powerpc", "ppc", "ppc64", "power macintosh"}: ++ return "powerpc" ++ return m ++ + def detect_arch(): + with open(Path(__file__).parent.parent / "libs.json") as f: + archs = json.loads(f.read()) + + uname = platform.uname() + uname_system = "Android" if is_android_env() else uname.system ++ uname_machine = normalize_machine(uname.machine) + glibc_flavor = "gnueabihf" if uname.machine in ["armv7l", "armv6l"] else "gnu" + + libc, _ = platform.libc_ver() +@@ -42,14 +64,21 @@ def detect_arch(): + libc = "android" + pointer_size = struct.calcsize("P") * 8 + ++ # Check for installation via ports ++ use_macports = detect_macports_curl_impersonate() ++ + for arch in archs: + if ( + arch["system"] == uname_system +- and arch["machine"] == uname.machine ++ and arch["machine"] == uname_machine + and arch["pointer_size"] == pointer_size + and ("libc" not in arch or arch.get("libc") == libc) + ): +- if build_dir := os.environ.get("IMPERSONATE_BUILD_DIR"): ++ if use_macports and arch["system"] == "Darwin": ++ # Use MacPorts installation ++ arch["libdir"] = "@PREFIX@/lib" ++ arch["use_macports"] = True ++ elif build_dir := os.environ.get("IMPERSONATE_BUILD_DIR"): + arch["libdir"] = os.path.expanduser(build_dir) + elif arch.get("libdir"): + arch["libdir"] = os.path.expanduser(arch["libdir"]) +@@ -103,6 +132,11 @@ print(f"Using {libdir} to store libcurl-impersonate") + + + def download_libcurl(): ++ # Skip download if using MacPorts or system installation ++ if arch.get("use_macports"): ++ print(f"Using MacPorts curl-impersonate from {libdir}") ++ return ++ + expected = libdir / obj_name + if expected.exists(): + print(f"libcurl-impersonate: {expected} already downloaded.") +@@ -191,7 +225,7 @@ if is_static: + if system == "Darwin": + extra_link_args = [ + f"-Wl,-force_load,{static_libs[0]}", +- "-lc++", ++ "-l@CXXLIB@", + ] + elif is_android: + extra_link_args = [ +@@ -209,6 +243,25 @@ if is_static: + + libraries = get_curl_libraries() + ++# Determine include directories and compile flags ++if arch.get("use_macports"): ++ curl_include_dirs = [ ++ str(root_dir / "ffi"), ++ "@PREFIX@/include", ++ ] ++ extra_compile_flags = ["-DUSE_MACPORTS_CURL"] ++else: ++ curl_include_dirs = [ ++ str(root_dir / "include"), ++ str(root_dir / "ffi"), ++ str(libdir / "include"), ++ ] ++ extra_compile_flags = [] ++ ++# Add platform-specific compile flags ++if system == "Darwin": ++ extra_compile_flags.append("-Wno-implicit-function-declaration") ++ + ffibuilder.set_source( + "curl_cffi._wrapper", + """ +@@ -221,17 +274,11 @@ ffibuilder.set_source( + libraries=get_curl_libraries(), + extra_objects=[], # linked via extra_link_args + source_extension=".c", +- include_dirs=[ +- str(root_dir / "include"), +- str(root_dir / "ffi"), +- str(libdir / "include"), +- ], ++ include_dirs=curl_include_dirs, + sources=[ + str(root_dir / "ffi/shim.c"), + ], +- extra_compile_args=( +- ["-Wno-implicit-function-declaration"] if system == "Darwin" else [] +- ), ++ extra_compile_args=extra_compile_flags, + extra_link_args=extra_link_args, + ) + diff --git a/python/py-curl-cffi/files/patch-libs.json b/python/py-curl-cffi/files/patch-libs.json new file mode 100644 index 0000000000000..37629c29c94f0 --- /dev/null +++ b/python/py-curl-cffi/files/patch-libs.json @@ -0,0 +1,46 @@ +diff --git a/libs.json b/libs.json +index 8fcfc2b..07f2dc4 100644 +--- libs.json ++++ libs.json +@@ -34,8 +34,8 @@ + "machine": "x86_64", + "pointer_size": 64, + "sysname": "macos", +- "link_type": "static", +- "obj_name": "libcurl-impersonate.a", ++ "link_type": "dynamic", ++ "obj_name": "libcurl-impersonate.dylib", + "arch": "x86_64" + }, + { +@@ -43,10 +43,28 @@ + "machine": "arm64", + "pointer_size": 64, + "sysname": "macos", +- "link_type": "static", +- "obj_name": "libcurl-impersonate.a", ++ "link_type": "dynamic", ++ "obj_name": "libcurl-impersonate.dylib", + "arch": "arm64" + }, ++ { ++ "system": "Darwin", ++ "machine": "powerpc", ++ "pointer_size": 32, ++ "sysname": "macos", ++ "link_type": "dynamic", ++ "obj_name": "libcurl-impersonate.dylib", ++ "arch": "ppc" ++ }, ++ { ++ "system": "Darwin", ++ "machine": "powerpc", ++ "pointer_size": 64, ++ "sysname": "macos", ++ "link_type": "dynamic", ++ "obj_name": "libcurl-impersonate.dylib", ++ "arch": "ppc64" ++ }, + { + "system": "Linux", + "machine": "x86_64",