Version in base suite: 0.4.8.16-1 Base version: tor_0.4.8.16-1 Target version: tor_0.4.9.6-0+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/t/tor/tor_0.4.8.16-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/t/tor/tor_0.4.9.6-0+deb13u1.dsc CODE_OF_CONDUCT | 3 ChangeLog | 1038 LICENSE | 27 Makefile.am | 8 Makefile.in | 589 README.md | 13 ReleaseNotes | 576 acinclude.m4 | 5 configure | 397 configure.ac | 123 contrib/win32build/tor-mingw.nsi.in | 2 debian/.debian-ci.yml | 18 debian/changelog | 67 debian/micro-revision.i | 2 debian/misc/backport | 4 debian/misc/build-tor-sources | 553 debian/tests/control | 2 debian/tests/setup-onion-service | 10 doc/asciidoc-helper.sh | 6 doc/man/tor-gencert.1.in | 4 doc/man/tor-print-ed-signing-cert.1.in | 4 doc/man/tor-resolve.1.in | 4 doc/man/tor.1.in | 110 doc/man/tor.1.txt | 128 doc/man/tor.html.in | 186 doc/man/torify.1.in | 4 m4/ax_check_compile_flag.m4 | 76 orconfig.h.in | 46 scripts/maint/practracker/practracker.py | 4 src/app/config/config.c | 42 src/app/config/fallback_dirs.inc | 1002 src/app/config/include.am | 1 src/app/config/or_options_st.h | 17 src/app/config/resolve_addr.c | 9 src/app/config/tor_cmdline_mode.h | 1 src/app/main/main.c | 69 src/app/main/ntmain.c | 7 src/app/main/shutdown.c | 1 src/config/geoip |118318 +++++++++++++++----------- src/config/geoip6 |128280 ++++++++++++++++++++++++----- src/config/torrc.sample.in | 4 src/core/crypto/hs_ntor.c | 9 src/core/crypto/include.am | 16 src/core/crypto/onion_crypto.c | 313 src/core/crypto/onion_crypto.h | 16 src/core/crypto/onion_tap.c | 246 src/core/crypto/onion_tap.h | 40 src/core/crypto/relay_crypto.c | 448 src/core/crypto/relay_crypto.h | 45 src/core/crypto/relay_crypto_cgo.c | 583 src/core/crypto/relay_crypto_cgo.h | 206 src/core/crypto/relay_crypto_st.h | 40 src/core/crypto/relay_crypto_tor1.c | 313 src/core/crypto/relay_crypto_tor1.h | 33 src/core/crypto/tor1_crypt_st.h | 39 src/core/mainloop/connection.c | 29 src/core/mainloop/cpuworker.c | 26 src/core/mainloop/cpuworker.h | 2 src/core/mainloop/include.am | 6 src/core/mainloop/mainloop.c | 1 src/core/or/channel.c | 5 src/core/or/channel.h | 1 src/core/or/channelpadding.c | 47 src/core/or/channelpadding.h | 4 src/core/or/channeltls.c | 98 src/core/or/circuit_st.h | 12 src/core/or/circuitbuild.c | 236 src/core/or/circuitbuild.h | 8 src/core/or/circuitlist.c | 16 src/core/or/circuitlist.h | 1 src/core/or/circuitpadding.c | 25 src/core/or/circuitpadding.h | 10 src/core/or/circuituse.c | 45 src/core/or/command.c | 23 src/core/or/conflux.c | 155 src/core/or/conflux.h | 25 src/core/or/conflux_cell.c | 61 src/core/or/conflux_cell.h | 10 src/core/or/conflux_params.c | 21 src/core/or/conflux_params.h | 1 src/core/or/conflux_pool.c | 92 src/core/or/conflux_pool.h | 10 src/core/or/conflux_st.h | 6 src/core/or/congestion_control_common.c | 110 src/core/or/congestion_control_common.h | 11 src/core/or/congestion_control_flow.c | 96 src/core/or/congestion_control_flow.h | 7 src/core/or/connection_edge.c | 413 src/core/or/connection_edge.h | 13 src/core/or/connection_or.c | 218 src/core/or/connection_or.h | 5 src/core/or/crypt_path.c | 63 src/core/or/crypt_path.h | 22 src/core/or/crypt_path_st.h | 15 src/core/or/dos.c | 127 src/core/or/dos.h | 34 src/core/or/dos_options.inc | 13 src/core/or/edge_connection_st.h | 12 src/core/or/extend_info_st.h | 9 src/core/or/extendinfo.c | 30 src/core/or/extendinfo.h | 2 src/core/or/half_edge_st.h | 4 src/core/or/include.am | 46 src/core/or/onion.c | 158 src/core/or/onion.h | 7 src/core/or/or.h | 119 src/core/or/or_circuit_st.h | 13 src/core/or/orconn_event.h | 18 src/core/or/policies.c | 8 src/core/or/protover.c | 28 src/core/or/protover.h | 8 src/core/or/reasons.c | 38 src/core/or/relay.c | 582 src/core/or/relay.h | 39 src/core/or/relay_crypto_st.h | 38 src/core/or/relay_msg.c | 286 src/core/or/relay_msg.h | 88 src/core/or/relay_msg_st.h | 47 src/core/or/scheduler_kist.c | 14 src/core/or/sendme.c | 228 src/core/or/sendme.h | 11 src/core/or/status.c | 7 src/core/or/versions.c | 15 src/core/proto/include.am | 2 src/core/proto/proto_socks.c | 37 src/ext/include.am | 29 src/ext/polyval/ctmul.c | 311 src/ext/polyval/ctmul64.c | 133 src/ext/polyval/pclmul.c | 253 src/ext/polyval/polyval.c | 561 src/ext/polyval/polyval.h | 185 src/feature/client/bridges.c | 6 src/feature/client/circpathbias.c | 62 src/feature/client/circpathbias.h | 6 src/feature/client/dnsserv.c | 3 src/feature/client/entrynodes.c | 17 src/feature/client/entrynodes.h | 2 src/feature/client/include.am | 2 src/feature/client/transports.c | 158 src/feature/client/transports.h | 6 src/feature/control/btrack_orconn_cevent.c | 4 src/feature/control/control.c | 4 src/feature/control/control_auth.c | 39 src/feature/control/control_auth.h | 4 src/feature/control/control_cmd.c | 47 src/feature/control/control_cmd.h | 3 src/feature/control/control_events.c | 17 src/feature/control/control_events.h | 5 src/feature/control/control_fmt.c | 18 src/feature/control/control_getinfo.c | 6 src/feature/control/include.am | 6 src/feature/dirauth/dirauth_config.c | 55 src/feature/dirauth/dirauth_options.inc | 3 src/feature/dirauth/dirvote.c | 189 src/feature/dirauth/dirvote.h | 36 src/feature/dirauth/process_descs.c | 14 src/feature/dirauth/voteflags.c | 17 src/feature/dircache/dircache.c | 8 src/feature/dircache/dirserv.c | 17 src/feature/dirclient/dirclient.c | 12 src/feature/dircommon/dir_connection_st.h | 4 src/feature/dircommon/directory.c | 34 src/feature/dircommon/directory.h | 1 src/feature/dircommon/include.am | 2 src/feature/dirparse/microdesc_parse.c | 18 src/feature/dirparse/parsecommon.c | 13 src/feature/dirparse/parsecommon.h | 3 src/feature/dirparse/routerparse.c | 258 src/feature/dirparse/routerparse.h | 10 src/feature/hibernate/hibernate.c | 9 src/feature/hibernate/hibernate.h | 1 src/feature/hibernate/include.am | 2 src/feature/hs/hs_cache.c | 44 src/feature/hs/hs_cache.h | 1 src/feature/hs/hs_cell.c | 23 src/feature/hs/hs_circuit.c | 16 src/feature/hs/hs_client.c | 3 src/feature/hs/hs_common.c | 2 src/feature/hs/hs_common.h | 9 src/feature/hs/hs_config.h | 2 src/feature/hs/hs_descriptor.c | 127 src/feature/hs/hs_service.c | 36 src/feature/hs/hs_service.h | 5 src/feature/hs/include.am | 10 src/feature/hs_common/include.am | 2 src/feature/metrics/include.am | 4 src/feature/nodelist/include.am | 4 src/feature/nodelist/microdesc.c | 6 src/feature/nodelist/microdesc_st.h | 14 src/feature/nodelist/networkstatus.c | 7 src/feature/nodelist/node_select.h | 2 src/feature/nodelist/nodelist.c | 155 src/feature/nodelist/nodelist.h | 9 src/feature/nodelist/routerinfo_st.h | 14 src/feature/nodelist/routerlist.c | 31 src/feature/nodelist/torcert.h | 1 src/feature/relay/circuitbuild_relay.c | 25 src/feature/relay/circuitbuild_relay.h | 11 src/feature/relay/dns.c | 33 src/feature/relay/dns.h | 4 src/feature/relay/ext_orport.c | 3 src/feature/relay/include.am | 4 src/feature/relay/onion_queue.c | 90 src/feature/relay/relay_config.c | 28 src/feature/relay/relay_handshake.c | 96 src/feature/relay/relay_handshake.h | 3 src/feature/relay/relay_metrics.c | 71 src/feature/relay/relay_metrics.h | 6 src/feature/relay/relay_periodic.c | 2 src/feature/relay/router.c | 167 src/feature/relay/router.h | 2 src/feature/relay/routerkeys.c | 353 src/feature/relay/routerkeys.h | 24 src/feature/relay/selftest.c | 16 src/feature/relay/selftest.h | 2 src/feature/rend/include.am | 4 src/feature/stats/geoip_stats.c | 9 src/feature/stats/geoip_stats.h | 7 src/feature/stats/include.am | 2 src/feature/stats/rephist.c | 35 src/feature/stats/rephist.h | 6 src/lib/cc/compat_compiler.h | 6 src/lib/compress/compress.c | 13 src/lib/conf/include.am | 6 src/lib/confmgt/include.am | 8 src/lib/crypt_ops/aes.h | 18 src/lib/crypt_ops/aes_nss.c | 145 src/lib/crypt_ops/aes_openssl.c | 442 src/lib/crypt_ops/compat_openssl.h | 28 src/lib/crypt_ops/crypto_dh.c | 20 src/lib/crypt_ops/crypto_dh.h | 2 src/lib/crypt_ops/crypto_dh_nss.c | 6 src/lib/crypt_ops/crypto_dh_openssl.c | 58 src/lib/crypt_ops/crypto_hkdf.c | 5 src/lib/crypt_ops/crypto_init.c | 3 src/lib/crypt_ops/crypto_openssl_mgt.c | 119 src/lib/crypt_ops/crypto_openssl_mgt.h | 20 src/lib/crypt_ops/crypto_rsa_openssl.c | 39 src/lib/crypt_ops/include.am | 6 src/lib/ctime/include.am | 4 src/lib/defs/dh_sizes.h | 5 src/lib/defs/include.am | 6 src/lib/dispatch/dispatch_cfg.c | 2 src/lib/dispatch/include.am | 4 src/lib/err/backtrace.h | 8 src/lib/evloop/token_bucket.c | 2 src/lib/evloop/workqueue.c | 193 src/lib/fdio/fdio.c | 28 src/lib/fdio/fdio.h | 1 src/lib/fdio/include.am | 2 src/lib/fs/conffile.c | 2 src/lib/fs/files.c | 7 src/lib/fs/files.h | 4 src/lib/fs/path.c | 3 src/lib/geoip/include.am | 2 src/lib/lock/include.am | 2 src/lib/log/log.c | 6 src/lib/log/log_sys.c | 29 src/lib/log/util_bug.c | 27 src/lib/log/util_bug.h | 29 src/lib/math/include.am | 6 src/lib/metrics/include.am | 8 src/lib/net/include.am | 4 src/lib/net/socket.c | 8 src/lib/osinfo/include.am | 4 src/lib/process/daemon.c | 3 src/lib/process/process_unix.c | 35 src/lib/process/restrict.c | 4 src/lib/process/waitpid.c | 3 src/lib/sandbox/sandbox.c | 268 src/lib/sandbox/sandbox.h | 3 src/lib/smartlist_core/include.am | 6 src/lib/string/util_string.c | 2 src/lib/term/include.am | 2 src/lib/time/compat_time.c | 9 src/lib/time/compat_time.h | 4 src/lib/time/include.am | 2 src/lib/tls/ciphers.inc | 38 src/lib/tls/ciphers_v13.inc | 15 src/lib/tls/include.am | 1 src/lib/tls/tortls.c | 59 src/lib/tls/tortls.h | 20 src/lib/tls/tortls_internal.h | 20 src/lib/tls/tortls_nss.c | 121 src/lib/tls/tortls_openssl.c | 939 src/lib/tls/tortls_st.h | 10 src/lib/tls/x509_openssl.c | 11 src/test/bench.c | 261 src/test/cgo_vectors.inc | 651 src/test/compression_bomb.h | 864 src/test/fakecircs.c | 7 src/test/include.am | 51 src/test/test.c | 211 src/test/test.h | 1 src/test/test_bridges.c | 12 src/test/test_cell_formats.c | 868 src/test/test_circuitbuild.c | 36 src/test/test_circuitlist.c | 10 src/test/test_circuitpadding.c | 54 src/test/test_config.c | 4 src/test/test_conflux_cell.c | 17 src/test/test_conflux_pool.c | 26 src/test/test_crypto.c | 293 src/test/test_crypto_cgo.c | 647 src/test/test_crypto_ope.c | 4 src/test/test_crypto_openssl.c | 5 src/test/test_dir.c | 253 src/test/test_dirvote.c | 25 src/test/test_entrynodes.c | 73 src/test/test_extorport.c | 2 src/test/test_geoip.c | 13 src/test/test_hs_client.c | 22 src/test/test_hs_control.c | 17 src/test/test_hs_intropoint.c | 2 src/test/test_hs_service.c | 12 src/test/test_include.sh | 2 src/test/test_link_handshake.c | 111 src/test/test_microdesc.c | 112 src/test/test_nodelist.c | 20 src/test/test_ntor_v3.c | 7 src/test/test_proto_http.c | 27 src/test/test_protover.c | 10 src/test/test_rebind.sh | 2 src/test/test_relaycell.c | 231 src/test/test_relaycrypt.c | 21 src/test/test_router.c | 4 src/test/test_routerkeys.c | 84 src/test/test_sandbox.c | 20 src/test/test_sendme.c | 139 src/test/test_socks.c | 65 src/test/test_status.c | 13 src/test/test_tortls.c | 232 src/test/test_tortls.h | 1 src/test/test_tortls_openssl.c | 520 src/test/test_util.c | 36 src/test/test_util_format.c | 2 src/tools/include.am | 10 src/tools/tor-resolve.c | 2 src/trunnel/include.am | 41 src/trunnel/link_handshake.c | 1562 src/trunnel/link_handshake.h | 632 src/trunnel/sendme_cell.c | 84 src/trunnel/sendme_cell.h | 25 src/trunnel/subproto_request.c | 456 src/trunnel/subproto_request.h | 157 345 files changed, 193343 insertions(+), 80888 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpl89dm1lw/tor_0.4.8.16-1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpl89dm1lw/tor_0.4.9.6-0+deb13u1.dsc: no acceptable signature found diff -Nru tor-0.4.8.16/CODE_OF_CONDUCT tor-0.4.9.6/CODE_OF_CONDUCT --- tor-0.4.8.16/CODE_OF_CONDUCT 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/CODE_OF_CONDUCT 2026-03-25 14:30:34.000000000 +0000 @@ -3,5 +3,4 @@ participate. For the latest version of our Code of Conduct, please see -https://gitweb.torproject.org/community/policies.git/plain/code_of_conduct.txt - +https://community.torproject.org/policies/code_of_conduct/ diff -Nru tor-0.4.8.16/ChangeLog tor-0.4.9.6/ChangeLog --- tor-0.4.8.16/ChangeLog 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/ChangeLog 2026-03-25 14:30:34.000000000 +0000 @@ -1,20 +1,872 @@ -Changes in version 0.4.8.16 - 2025-03-24 - This is quick second release since 0.4.8.15 due to a typo in a directory - authority rule file. This only affects directory authorities. Regardless, - upgrading to latest stable is always desired. +Changes in version 0.4.9.6 - 2026-03-25 + This is a security release fixing major bugfixes that could possibly lead to + remote crashing relays. We strongly recommend upgrading as soon as possible. + + o Major bugfix (security): + - Fix a stack overflow of 11 bytes on malicious CREATED2. This lead + to a remote crash. TROVE-2026-003. Reported-by: Anas Cherni of + Calif.io. Fixes bug 41231; bugfix on 0.4.9.1-alpha. + + o Major bugfix (security, conflux): + - Fix a memory compare using the wrong length. This could lead to a + remote crash when using the conflux subsystem. TROVE-2026-004. + Fixes bug 41232; bugfix on 0.4.8.1-alpha. + + o Minor bugfixes (security): + - Fix a series of defense in depth security issues found across the + codebase. Fixes bug 41228; bugfix on 0.3.5.1-alpha. + + o Minor bugfixes (portability): + - (Hopefully) fix our polyval implementation on big-endian + platforms. Fixes bug 41215; bugfix on 0.4.9.3-alpha. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on March 25, 2026. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2026/03/25. + + +Changes in version 0.4.9.5 - 2026-02-12 + This first stable release in the 0.4.9 series introduces a new + circuit-level encryption design for better client security, as well + as a more scalable way for large relay operators to annotate which + relays they run so clients can avoid using too many of them in a + single circuit. + + o Major features (cryptography): + - Clients and relays can now negotiate Counter Galois Onion (CGO) + relay cryptography, as designed by Jean Paul Degabriele, + Alessandro Melloni, Jean-Pierre Münch, and Martijn Stam. CGO + provides improved resistance to several kinds of tagging attacks, + better forward secrecy, and better forgery resistance. Closes + ticket 41047. Implements proposal 359. + + o Major features (path selection): + - Clients and relays now support "happy families", a system to + simplify relay family operation and improve directory performance. + With "happy families", relays in a family share a secret "family + key", which they use to prove their membership in the family. + Implements proposal 321; closes ticket 41009. Note that until + enough clients are upgraded, relay operators will still need to + configure MyFamily lists. But once clients no longer depend on + those lists, we will be able to remove them entirely, thereby + simplifying family operation, and making microdescriptor downloads + approximately 80% smaller. For more information, see + https://community.torproject.org/relay/setup/post-install/family-ids/ + + o Major bugfixes (conflux): + - Ensure conflux guards obey family and subnet restrictions. Fixes + bug 40976; bugfix on 0.4.8.1-alpha. + + o Major bugfixes (controller events): + - Fix spikes occurring in bandwidth cache events on control connection. + Fixes bug 31524; bugfix on 0.0.9pre5. + + o Major bugfixes (sandbox): + - Fix sandbox to work on architectures that use Linux's generic + syscall interface, extending support for AArch64 (ARM64) and + adding support for RISC-V, allowing test_include.sh and the + sandbox unit tests to pass on these systems even when building + with fragile hardening enabled. Fixes bugs 40465 and 40599; bugfix + on 0.2.5.1-alpha. + + o Minor features (client security, reliability): + - When KeepaliveIsolateSOCKSAuth is keeping a circuit alive, expire + the circuit based on when it was last in use for any stream, not + (as we did before) based on when a stream was last attached to it. + Closes ticket 41157. Implements a minimal version of Proposal 368. + + o Minor features (exit relays): + - Implement reevaluating new exit policy against existing + connections. This is controlled by new config option + ReevaluateExitPolicy, defaulting to 0. Closes ticket 40676. + - Implement a token-bucket based rate limiter for stream creation + and resolve request. It is configured by the DoSStream* family of + configuration options. Closes ticket 40736. + - Add Monero ports to the ReducedExitPolicy. Closes ticket 41168. + + o Minor features (bridges): + - Save complete bridge lines to 'datadir/bridgelines'. Closes + ticket 29128. + + o Minor features (client extensibility): + - Implement new HTTPTunnelPort features for interoperability with + Arti's HTTP CONNECT proxy. This work adds new headers to requests + to and replies from the HttpConnectPort, support for OPTIONS + requests, tightens the expected syntax for Proxy-Authorization, + and increases defense-in-depth against some kinds of cross-site + HTTP attacks. Closes ticket 41156. Implements proposal 365. + - Detect invalid SOCKS5 username/password combinations according to + new extended parameters syntax. (Currently, this rejects any + SOCKS5 username beginning with "", except for the username + "0". Such usernames are now reserved to communicate + additional parameters with other Tor implementations.) Implements + proposal 351. + + o Minor features (sandboxing): + - Allow the fstatat64 and statx syscalls on i386 architecture when + glibc >= 2.33. On i386, glibc uses fstatat64 instead of newfstatat + for stat operations, and statx for time64 support. Without this, + SIGHUP configuration reload fails when using sandbox mode with + %include directives on i386 with Debian Bookworm or newer. + - Allow the lstat64 syscall on i386 architecture. This syscall is + used by glob() in glibc 2.36+ when processing %include directives + with directory patterns. + + o Minor features (security): + - Increase the size of our finite-field Diffie Hellman TLS group + (which we should never actually use!) to 2048 bits. Part of + ticket 41067. + - Require TLS version 1.2 or later. (Version 1.3 support will be + required in the near future.) Part of ticket 41067. + - Update TLS 1.2 client cipher list to match current Firefox. Part + of ticket 41067. + - Verify needle is smaller than haystack before calling memmem. + Closes ticket 40854. + + o Minor features (onion services): + - Add 3 more keywords to the ADD_ONION control command: + PoWDefensesEnabled, PoWQueueRate and PoWQueueBurst which correspond + to HiddenServicePoWDefensesEnabled, HiddenServicePoWQueueRate and + HiddenServicePoWQueueBurst from torrc. + - Reduce the minimum value of hsdir_interval to match recent tor- + spec change. + + o Minor feature (directory authority): + - Introduce MinimalAcceptedServerVersion to allow configuring + the minimum accepted relay version without requiring a new tor + release. Closes ticket 40817. + + o Minor features (metrics port): + - New metrics on the MetricsPort for the number of BUG() calls that + occurred at runtime. Fixes bugs 40839 and 41104; bugfix on + 0.4.7.1-alpha. + - Handle rephist tracking of ntor and ntor_v3 handshakes + individually such that MetricsPort exposes the correct values. + Fixes bug 40638; bugfix on 0.4.7.11. + - Add new metrics for relays on the MetricsPort namely the count of + drop cell, destroy cell and the number of circuit protocol + violation seen that lead to a circuit close. Closes ticket 40816. + + o Minor features (forward-compatibility): + - We now correctly parse microdescriptors and router descriptors + that do not include TAP onion keys. (For backward compatibility, + authorities continue to require these keys.) Implements part of + proposal 350. + + o Minor features (portability, android): + - Use /data/local/tmp for data storage on Android by default. Closes + ticket 40487. Patch from Hans-Christoph Steiner. + + o Minor features (directory authority): + - Export unsigned consensus documents once we have seen a threshold + of signatures, as a step toward the consensus transparency + experiment. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on February 12, 2026. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, + as retrieved on 2026/02/12. + + o Minor features (windows): + - Various compilation fixes for our Windows CI. Closes ticket 41214. + + o Minor bugfixes (exit relays): + - Clip every returned DNS TTL to 60 (RESOLVED) in order to mitigate + an exit DNS cache oracle. Fixes bug 40979; bugfix on 0.3.5.1-alpha. + + o Minor bugfixes (spec conformance): + - Set the length field correctly on RELAY_COMMAND_CONFLUX_SWITCH + messages. Previously, it was always set to the maximum value. + Fixes bug 41056; bugfix on 0.4.8.1-alpha. + - Do not treat "15" as a recognized remote END reason code. + Formerly, we treated it as synonymous with a local ENTRYPOLICY, + which isn't a valid remote code at all. Fixes bug 41171; bugfix + on 0.2.0.8-alpha. + + o Minor bugfixes (tooling): + - Fix a false positive valgrind related to inspecting a bitfield + next to another uninitialized bitfield. Fixes bug 41182; bugfix + on 0.3.3.2-alpha. + - Fix minor warnings from newer versions of shellcheck and clang. + Fixes bug 41166; bugfix on 0.4.3.1-alpha and several + other versions. + - Fix a warning when compiling with GCC 14.2. Closes 41032. + + o Minor bugfixes (threads): + - Make thread control POSIX compliant. Fixes bug 41109; bugfix + on 0.4.8.17. + + o Minor bugfix (client DNS): + - Handle empty DNS reply without sending back an error and instead + send back NOERROR (RFC1035 error code 0x0). Fixes bug 40248; + bugfix on 0.3.5.1-alpha. + + o Minor bugfixes (directory authorities): + - After we added layer-two vanguards, directory authorities wouldn't + think any of their vanguards were suitable for circuits, leading + to a "Failed to find node for hop #2 of our path. Discarding this + circuit." log message once per second from startup until they made + a fresh consensus. Now they look to their existing consensus on + startup, letting them build circuits properly from the beginning. + Fixes bug 40802; bugfix on 0.4.7.1-alpha. + + o Minor bugfixes (tests): + - Fix a test failure with OpenSSL builds running at security level 1 + or greater, which does not permit SHA-1 certificates. Fixes bug + 41021; bugfix on 0.2.8.1-alpha. + + o Minor bugfixes (bridges): + - Don't warn when BridgeRelay is 1 and ExitRelay is explicitly set + to 0. Fixes bug 40884; bugfix on 0.4.8.3-rc. + + o Minor bugfixes (conflux, client): + - Avoid a non fatal assert caused by data coming in on a conflux set + that is being freed during shutdown. Fixes bug 40870; bugfix + on 0.4.8.1-alpha. + + o Minor bugfixes (testing network): + - Enabling TestingTorNetwork no longer forces fast hidden service + intro point rotation. This reduces noise and errors when using + hidden services with TestingTorNetwork enabled. Fixes bug 40922; + bugfix on 0.3.2.1-alpha. + + o Minor bugfixes (relay): + - Refuse to overwrite an existing *.secret_family_key when running + tor --keygen-family. Fixes bug 41184; bugfix on 0.4.9.1-alpha. + + o New system requirements: + - When built with LibreSSL, Tor now requires LibreSSL 3.7 or later. + Part of ticket 41059. + - When built with OpenSSL, Tor now requires OpenSSL 1.1.1 or later. + (We strongly recommend 3.0 or later, but still build with 1.1.1, + even though it is not supported by the OpenSSL team, due to its + presence in Debian oldstable.) Part of ticket 41059. + + o Removed features (relays): + - Relays no longer support clients that falsely advertise TLS + ciphers they don't really support. (Clients have not done this + since 0.2.3.17-beta). Part of ticket 41031. + - Relays no longer support clients that require obsolete v1 and v2 + link handshakes. (The v3 link handshake has been supported since + 0.2.3.6-alpha). Part of ticket 41031. + - Relays no longer support the obsolete TAP circuit extension + protocol. (For backward compatibility, however, relays still + continue to include TAP keys in their descriptors.) Implements + part of proposal 350. + - Relays no longer support the obsolete "RSA-SHA256-TLSSecret" + authentication method, which used a dangerously short RSA key, and + which required access TLS session internals. The current method + ("Ed25519-SHA256-RFC5705") has been supported since 0.3.0.1-alpha. + Closes ticket 41020. + + o Removed features (directory authorities): + - Directory authorities no longer support consensus methods before + method 32. Closes ticket 40835. + - We include a new consensus method that removes support for + computing "package" lines in consensus documents. This feature was + never used, and support for including it in our votes was removed + in 0.4.2.1-alpha. Finishes implementation of proposal 301. + + +Changes in version 0.4.9.4-rc - 2026-01-28 + Finally, the release candidate for the 0.4.9.x series. It consists of minor + features and several bugfixes. Nothing major has been added since the alpha. + If everything goes well, the next version will be the first stable. + + o Minor features (security, reliability): + - When KeepaliveIsolateSOCKSAuth is keeping a circuit alive, expire + the circuit based on when it was last in use for any stream, not + (as we did before) based on when a stream was last attached to it. + Closes ticket 41157. Implements a minimal version of Proposal 368. + + o Minor feature (Exit): + - Add Monero ports to the ReducedExitPolicy. Closes ticket 41168. + + o Minor features (HTTPTunnelPort): + - Implement new HTTPTunnelPort features for interoperability with + Arti's HTTP CONNECT proxy. This work adds new headers to requests + to and replies from the HttpConnectPort, support for OPTIONS + requests, tightens the expected syntax for Proxy-Authorization, + and increases defense-in-depth against some kinds of cross-site + HTTP attacks. Closes ticket 41156. Implements proposal 365. + + o Minor features (linux seccomp2 sandbox): + - Allow the fstatat64 and statx syscalls on i386 architecture when + glibc >= 2.33. On i386, glibc uses fstatat64 instead of newfstatat + for stat operations, and statx for time64 support. Without this, + SIGHUP configuration reload fails when using sandbox mode with + %include directives on i386 with Debian Bookworm or newer. + - Allow the lstat64 syscall on i386 architecture. This syscall is + used by glob() in glibc 2.36+ when processing %include directives + with directory patterns. + + o Minor bugfixes (DNS, exit): + - Clip every returned DNS TTL to 60 (RESOLVED) in order to mitigate + an exit DNS cache oracle. Fixes bug 40979; bugfix on 0.3.5.1-alpha. + + o Minor bugfixes (spec conformance): + - Do not treat "15" as a recognized remote END reason code. + Formerly, we treated it as synonymous with a local ENTRYPOLICY, + which isn't a valid remote code at all. Fixes bug 41171; bugfix + on 0.2.0.8-alpha. + + o Minor bugfixes (tooling): + - Fix a false positive valgrind related to inspecting a bitfield + next to another uninitialized bitfield. Fixes bug 41182; bugfix + on 0.3.3.2-alpha. + + o Minor bugfixes (warnings): + - Fix minor warnings from newer versions of shellcheck and clang. + Fixes bug 41166; bugfix on 0.4.3.1-alpha and several + other versions. + + +Changes in version 0.4.8.22 - 2026-01-28 + This is likely the very last release of the 0.4.8.x series. Three major + bugfixes detailed below including two affecting directory servers (basically + all relays). We strongly recommend upgrading as soon as possible. + + o Major bugfixes (security): + - Avoid an out-of-bounds read error that could occur with + V1-formatted EXTEND cells. Fixes bug 41180; bugfix on 0.4.8.1-alpha. + This is tracked as TROVE-2025-016. + + o Major bugfixes (directory servers): + - Allow old clients to fetch the consensus even if they use version + 0 of the SENDME protocol. In mid 2025 we changed the required + minimum version of the "FlowCtrl" protocol to 1, meaning directory + caches hang up on clients that send a version 0 SENDME cell. Since + old clients were no longer able to retrieve the consensus, they + couldn't learn about this required minimum version -- meaning + we've had many many old clients loading down directory servers for + the past months. Fixes bug 41191; bugfix on 0.4.1.1-alpha. + - Don't count networkstatus serves until they finish. When we + started serving a consensus document but the client didn't receive + all of it, we were still counting that as a success in our stats. + This mistake, which can be triggered for example by obsolete + clients or by DPI-based censorship, led to wildly inflated user + counts because we estimate total users in the world based on + successful consensus fetches. Fixes bug 41192; bugfix + on 0.2.1.1-alpha. + + o Minor feature (testing, CI): + - Bump the CI version of chutney to the current version as of + 2026-01-21 (3338f5c). + + o Minor features (debugging, compression): + - Do not check for compression bombs for buffers smaller than 5MB + (increased from 64 KB). Fixes ticket 40739; bugfix on 0.2.1.29. + + o Minor features (directory servers): + - Track how many times directory servers begin serving networkstatus + documents, so we can compare it to the number of times we finish + serving them. Motivated by the fixes in ticket 41192. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on January 28, 2026. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2026/01/28. + + o Minor bugfixes (relay): + - Downgrade "Error relaying cell across rendezvous" log warn to info + as the error condition is possible under normal circumstances. Fixes + bug 40951; bugfix on 0.3.5.1-alpha. + + o Code simplification and refactoring: + - Simplify SOCKS4a parsing to avoid the (false) appearance of + integer underflows, and to make the logic more obvious. Fixes bug + 41190; bugfix on 0.3.5.1-alpha. + + +Changes in version 0.4.8.21 - 2025-11-17 + This release is a continuation of the previous one and addresses additional + Conflux-related issues identified through further testing and feedback from + relay operators. We strongly recommend upgrading as soon as possible. + + o Major bugfixes (conflux, exit): + - When dequeuing out-of-order conflux cells, the circuit could be + closed in between two dequeues, which could lead to mishandling + a NULL pointer. Fixes bug 41162; bugfix on 0.4.8.4. + + o Minor feature (compiler flag): + - Add -mbranch-protection=standard for arm64. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on November 17, 2025. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/11/17. + + o Minor bugfixes (bridges, pluggable transport): + - Fix a bug causing the initial tor process to hang instead of + exiting with RunAsDaemon, when pluggable transports are used. + Fixes bug 41088; bugfix on 0.4.8.1-alpha. + + +Changes in version 0.4.8.20 - 2025-11-10 + This release fixes several bugs related to Conflux edge cases as well as + adding a new hardening compiler flag if supported. + + o Minor feature (compiler flag): + - Add -fcf-protection=full if supported by the compiler. + Implements ticket 41139. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on November 10, 2025. o Minor features (geoip data): - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/11/10. + + o Minor bugfixes (conflux fragile asserts): + - Fix the root cause of some conflux fragile asserts when a control + port listener is attached. Fixes bug 41037; bugfix on 0.4.8.16. + + o Minor bugfixes (conflux, relay): + - Fix a series of conflux edge cases about sequence number + arithmetic and OOM handler kicking in under heavy memory pressure. + Fixes bug 41155; bugfix on 0.4.8.4. + + +Changes in version 0.4.8.19 - 2025-10-06 + This release provides major bugfixes for a LibreSSL issue and a flow control + C-tor specific problem (not protocol). We strongly recommend you upgrade as + soon as possible. + + o Major bugfixes (client, TLS): + - Fix some clients not being able to connect to LibreSSL relays. + Fixes bug 41134; bugfix on 0.4.8.17. + + o Minor bugfixes (stream flow control performance): + - Use a 5 ms grace period to allow an edge connection to flush its + stream data to the socket before sending an XOFF. This + significantly reduces the number of XON/XOFF messages sent when + (1) the application is reading stream data at a fast rate, and (2) + conflux is enabled. Fixes part of bug 41130; bugfix on 0.4.7.2-alpha. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on October 06, 2025. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/10/06. + + o Minor bugfix (process): + - Avoid closing all possible FDs when spawning a process (PT). On + some systems, this could lead to 3+ minutes hang. Fixes bug 40990; + bugfix on 0.3.5.1-alpha. + + +Changes in version 0.4.9.3-alpha - 2025-09-16 + This is the third alpha release and likely the last before going stable. + This release contains the new CGO circuit encryption. See proposal 359 for + more details. Several TLS minor fixes which will strengthen the link + security. + + o New system requirements: + - When built with LibreSSL, Tor now requires LibreSSL 3.7 or later. + Part of ticket 41059. + - When built with OpenSSL, Tor now requires OpenSSL 1.1.1 or later. + (We strongly recommend 3.0 or later, but still build with 1.1.1, + even though it is not supported by the OpenSSL team, due to its + presence in Debian oldstable.) Part of ticket 41059. + + o Major features (cell format): + - Tor now has (unused) internal support to encode and decode relay + messages in the new format required by our newer CGO encryption + algorithm. Closes ticket 41051. Part of proposal 359. + + o Major features (cryptography): + - Clients and relays can now negotiate Counter Galois Onion (CGO) + relay cryptography, as designed by Jean Paul Degabriele, + Alessandro Melloni, Jean-Pierre Münch, and Martijn Stam. CGO + provides improved resistance to several kinds of tagging attacks, + better forward secrecy, and better forgery resistance. Closes + ticket 41047. Implements proposal 359. + + o Major bugfixes (onion service directory cache): + - Preserve the download counter of an onion service descriptor + across descriptor uploads, so that recently updated descriptors + don't get pruned if there is memory pressure soon after update. + Additionally, create a separate torrc option MaxHSDirCacheBytes + that defaults to the former 20% of MaxMemInQueues threshold, but + can be controlled by relay operators under DoS. Also enforce this + threshold during HSDir uploads. Fixes bug 41006; bugfix + on 0.4.8.14. + + o Minor features (security): + - Increase the size of our finite-field Diffie Hellman TLS group + (which we should never actually use!) to 2048 bits. Part of + ticket 41067. + - Require TLS version 1.2 or later. (Version 1.3 support will be + required in the near future.) Part of ticket 41067. + - Update TLS 1.2 client cipher list to match current Firefox. Part + of ticket 41067. + + o Minor features (security, TLS): + - When we are running with OpenSSL 3.5.0 or later, support using the + ML-KEM768 for post-quantum key agreement. Closes ticket 41041. + + o Minor feature (client, TLS): + - Set the TLS 1.3 cipher list instead of falling back on the + default value. + + o Minor feature (padding, logging): + - Reduce the amount of messages being logged related to channel + padding timeout when log level is "notice". + + o Minor features (bridges): + - Save complete bridge lines to 'datadir/bridgelines'. Closes + ticket 29128. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on September 16, 2025. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/09/16. + + o Minor features (hidden services): + - Reduce the minimum value of hsdir_interval to match recent tor- + spec change. + + o Minor features (hsdesc POW): + - Tolerate multiple PoW schemes in onion service descriptors, for + future extensibility. Implements torspec ticket 272. + + o Minor features (performance TLS): + - When running with with OpenSSL 3.0.0 or later, support using + X25519 for TLS key agreement. (This should slightly improve + performance for TLS session establishment.) + + o Minor features (portability): + - Fix warnings when compiling with GCC 15. Closes ticket 41079. + + o Minor bugfix (conflux): + - Remove the pending nonce if we realize that the nonce of the + unlinked circuit is not tracked anymore. Should avoid the non + fatal assert triggered with a control port circuit event. Fixes + bug 41037; bugfix on 0.4.8.15. + + o Minor bugfixes (bridges, pluggable transport): + - Fix a bug causing the initial tor process to hang instead of + exiting with RunAsDaemon, when pluggable transports are used. + Fixes bug 41088; bugfix on 0.4.9.1-alpha. + + o Minor bugfixes (circuit handling): + - Prevent circuit_mark_for_close() from being called twice on the + same circuit. Fixes bug 40951; bugfix on 0.4.8.16-dev. + - Prevent circuit_mark_for_close() from being called twice on the + same circuit. Second fix attempt Fixes bug 41106; bugfix + on 0.4.8.17 + + o Minor bugfixes (compilation): + - Fix linking on systems without a working stdatomic.h. Fixes bug + 41076; bugfix on 0.4.9.1-alpha. + + o Minor bugfixes (compiler warnings): + - Make sure the two bitfields in the half-closed edge struct are + unsigned, as we're using them for boolean values and assign 1 to + them. Fixes bug 40911; bugfix on 0.4.7.2-alpha. + + o Minor bugfixes (logging, metrics port): + - Count BUG statements for the MetricsPort only if they are warnings + or errors. Fixes bug 41104; bugfix on 0.4.7.1-alpha. Patch + contributed by shadowcoder. + + o Minor bugfixes (protocol): + - Set the length field correctly on RELAY_COMMAND_CONFLUX_SWITCH + messages. Previously, it was always set to the maximum value. + Fixes bug 41056; bugfix on 0.4.8.1-alpha. + + o Minor bugfixes (relay): + - Fix a crash when FamilyKeyDir is a path that cannot be read. Fixes + bug 41043; bugfix on 0.4.9.2-alpha. + + o Minor bugfixes (threads): + - Make thread control POSIX compliant. Fixes bug 41109; bugfix + on 0.4.8.17-dev. + + o Removed features: + - Relays no longer support clients that falsely advertise TLS + ciphers they don't really support. (Clients have not done this + since 0.2.3.17-beta). Part of ticket 41031. + - Relays no longer support clients that require obsolete v1 and v2 + link handshakes. (The v3 link handshake has been supported since + 0.2.3.6-alpha). Part of ticket 41031. + + +Changes in version 0.4.8.18 - 2025-09-16 + This is a minor release with a major onion service directory cache (HSDir) + bug fix. A series of minor bugfixes as well. As always, we strongly recommend + to upgrade as soon as possible. + + o Major bugfixes (onion service directory cache): + - Preserve the download counter of an onion service descriptor + across descriptor uploads, so that recently updated descriptors + don't get pruned if there is memory pressure soon after update. + Additionally, create a separate torrc option MaxHSDirCacheBytes + that defaults to the former 20% of MaxMemInQueues threshold, but + can be controlled by relay operators under DoS. Also enforce this + threshold during HSDir uploads. Fixes bug 41006; bugfix + on 0.4.8.14. + + o Minor feature (padding, logging): + - Reduce the amount of messages being logged related to channel + padding timeout when log level is "notice". + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on September 16, 2025. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/09/16. + + o Minor bugfix (conflux): + - Remove the pending nonce if we realize that the nonce of the + unlinked circuit is not tracked anymore. Should avoid the non + fatal assert triggered with a control port circuit event. Fixes + bug 41037; bugfix on 0.4.8.15. + + o Minor bugfixes (circuit handling): + - Prevent circuit_mark_for_close() from being called twice on the + same circuit. Second fix attempt Fixes bug 41106; bugfix + on 0.4.8.17. + + +Changes in version 0.4.8.17 - 2025-06-30 + This is a minor providing a series of minor features especially in the realm + of TLS. It also brings a new set of recommended and required sub protocols. + And finally, few minor bugfixes, nothing major. As always, we strongly + recommend you upgrade as soon as possible. + + o Minor features (security, TLS): + - When we are running with OpenSSL 3.5.0 or later, support using the + ML-KEM768 for post-quantum key agreement. Closes ticket 41041. + + o Minor feature (client, TLS): + - Set the TLS 1.3 cipher list instead of falling back on the + default value. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on June 30, 2025. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/06/30. + + o Minor features (hsdesc POW): + - Tolerate multiple PoW schemes in onion service descriptors, for + future extensibility. Implements torspec ticket 272. + + o Minor features (performance TLS): + - When running with with OpenSSL 3.0.0 or later, support using + X25519 for TLS key agreement. (This should slightly improve + performance for TLS session establishment.) + + o Minor features (portability): + - Fix warnings when compiling with GCC 15. Closes ticket 41079. + + o Minor features (recommended protocols): + - Directory authorities now vote to recommend that clients support + certain protocols beyond those that are required. These include + improved support for connecting to relays on IPv6, NtorV3, and + congestion control. Part of ticket 40836. + + o Minor features (required protocols): + - Directory authorities now vote to require clients to support the + authenticated SENDME feature, which was introduced in + 0.4.1.1-alpha. Part of ticket 40836. + - Directory authorities now vote to require relays to support + certain protocols, all of which have been implemented since + 0.4.7.4-alpha or earlier. These include improved support for + connecting to relays on IPv6, NtorV3, running as a rate-limited + introduction point, authenticated SENDMEs, and congestion control. + Part of ticket 40836. + + o Minor bugfix (conflux): + - Avoid a non fatal assert when describing a conflux circuit on the + control port after being prepped to be freed. Fixes bug 41037; + bugfix on 0.4.8.15. + + o Minor bugfixes (circuit handling): + - Prevent circuit_mark_for_close() from being called twice on the + same circuit. Fixes bug 40951; bugfix on 0.4.8.16-dev. + + o Minor bugfixes (compiler warnings): + - Make sure the two bitfields in the half-closed edge struct are + unsigned, as we're using them for boolean values and assign 1 to + them. Fixes bug 40911; bugfix on 0.4.7.2-alpha. + + o Minor bugfixes (threads, memory): + - Improvements in cleanup of resources used by threads. Fixes bug + 40991; bugfix on 0.4.8.13-dev. + - Rework start and exit of worker threads. + + +Changes in version 0.4.9.2-alpha - 2025-04-02 + This is the second alpha of the 0.4.9.x series. We have several new minor + features and a big one, the happy families that was long awaited by relay + operators. This release also fixes a number of bugs including major ones. + + o Major feature (happy families): + - Clients and relays now support "happy families", a system to + simplify relay family operation and improve directory performance. + With "happy families", relays in a family shares a secret "family + key", which they use to prove their membership in the family. + Implements proposal 321; closes ticket 41009. Note that until + enough clients are upgraded, relay operators will still need to + configure MyFamily lists. But once clients no longer depend on + those lists, we will be able to remove them entirely, thereby + simplifying family operation, and making microdescriptor downloads + approximately 80% smaller. For more information, see + https://community.torproject.org/relay/setup/post-install/family-ids/ + + o Major features (client): + - Clients now respect "happy families" per proposal 321. This + feature will eventually allow a much more compact representation + for relay families, for a significant savings in directory + download size. + + o Minor feature (onion service, control port): + - Add 3 more keywords to the ADD_ONION control command: + PoWDefensesEnabled, PoWQueueRate and PoWQueueBurst which correspond + to HiddenServicePoWDefensesEnabled, HiddenServicePoWQueueRate and + HiddenServicePoWQueueBurst from torrc. + + o Minor feature (testing, CI): + - Use a fixed version of chutney (be881a1e) instead of its current + HEAD. This version should also be preferred when testing locally. + + o Minor features (compilation): + - Fix a warning when compiling with GCC 14.2. Closes 41032. + + o Minor features (continuous integration): + - Upgrade CI runners to use Debian Bookworm instead of Bullseye. + Closes ticket 41029. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on February 05, 2025. + - Regenerate fallback directories generated on March 20, 2025. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/02/05. + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/03/20. + - Update the geoip files to match the IPFire Location Database, as retrieved on 2025/03/24. + o Minor features (recommended protocols): + - Directory authorities now vote to recommend that clients support + certain protocols beyond those that are required. These include + improved support for connecting to relays on IPv6, NtorV3, and + congestion control. Part of ticket 40836. + + o Minor features (required protocols): + - Directory authorities now vote to require clients to support the + authenticated SENDME feature, which was introduced in + 0.4.1.1-alpha. Part of ticket 40836. + - Directory authorities now vote to require relays to support + certain protocols, all of which have been implemented since + 0.4.7.4-alpha or earlier. These include improved support for + connecting to relays on IPv6, NtorV3, running as a rate-limited + introduction point, authenticated SENDMEs, and congestion control. + Part of ticket 40836. + + o Major bugfix (control-events, bw-cache): + - Fixes spikes occurring in bandwidth cache on control connection. + Fixes bug 31524; bugfix on 0.4.8.12-dev. + + o Major bugfixes (conflux): + - Ensure conflux guards obey family and subnet restrictions. Fixes + bug 40976; bugfix on 0.4.8.13. + + o Major bugfixes (onion service directory cache): + - When the OOM killer kicks in, cleanup the descriptor cache of an + HSDir by looking at the lowest downloaded count instead of time in + cache. Fixes bug 40996; bugfix on 0.3.5.1-alpha. + + o Minor bugfix (client DNS): + - Handle empty DNS reply without sending back an error and instead + send back NOERROR (RFC1035 error code 0x0). Fixes bug 40248; + bugfix on 0.3.5.1-alpha. + + o Minor bugfix (conflux): + - Avoid a non fatal assert when describing a conflux circuit on the + control port after being prepped to be freed. Fixes bug 41037; + bugfix on 0.4.8.15. + o Minor bugfix (dirauth): - Fix typo in flag assignment approved-routers file. Fixes bug 41035; bugfix on 0.4.8.15 + o Minor bugfixes (control port): + - Correctly report conflux pair information to controller fields + Fixes bug 40872; bugfix on 0.4.8.1-alpha + + o Minor bugfixes (directory authorities): + - After we added layer-two vanguards, directory authorities wouldn't + think any of their vanguards were suitable for circuits, leading + to a "Failed to find node for hop #2 of our path. Discarding this + circuit." log message once per second from startup until they made + a fresh consensus. Now they look to their existing consensus on + startup, letting them build circuits properly from the beginning. + Fixes bug 40802; bugfix on 0.4.7.1-alpha. + + o Minor bugfixes (relay flag usage): + - Fix client usage of the MiddleOnly flag so that MiddleOnly relays + are not used as HS IP or RP by clients or services. Additionally, + give dirauths the ability to remove specific flags, as an + alternative to MiddleOnly. Fixes bug 41023; bugfix on 0.4.7.2-alpha + + o Minor bugfixes (sandbox, bwauth): + - Fix sandbox to work for bandwidth authority. Fixes bug 40933; + bugfix on 0.2.2.1-alpha + + o Minor bugfixes (tests): + - Fix a test failure with OpenSSL builds running at security level 1 + or greater, which does not permit SHA-1 certificates. (Fixes bug + 41021; bugfix on 0.2.8.1-alpha.) + + o Minor bugfixes (threads, memory): + - Improvements in cleanup of resources used by threads. Fixes bug + 40991; bugfix on 0.4.8.13-dev. + - Rework start and exit of worker threads. + + o Removed features: + - Relays no longer support the obsolete "RSA-SHA256-TLSSecret" + authentication method, which used a dangerously short RSA key, and + which required access TLS session internals. The current method + ("Ed25519-SHA256-RFC5705") has been supported since 0.3.0.1-alpha. + Closes ticket 41020. + + +Changes in version 0.4.8.16 - 2025-03-24 + This is a quick second release since 0.4.8.15 due to a typo in a directory + authority rule file. This only affects directory authorities. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/03/24. + + o Minor bugfix (dirauth): + - Fix typo in flag assignment approved-routers file. Fixes bug + 41035; bugfix on 0.4.8.15. + + Changes in version 0.4.8.15 - 2025-03-20 This is a minor release fixing a sandbox issue for bandwidth authority and a conflux issue on the control port. It also has a client fix about relay flag - usage. We strongly recommend to update as soon as possible as usual. + usage. o Minor feature (testing, CI): - Use a fixed version of chutney (be881a1e) instead of its current @@ -32,18 +884,18 @@ retrieved on 2025/03/20. o Minor bugfixes (control port): - - Correctly report conflux pair information to controller fields - Fixes bug 40872; bugfix on 0.4.8.1-alpha + - Correctly report conflux pair information to controller fields. + Fixes bug 40872; bugfix on 0.4.8.1-alpha. o Minor bugfixes (relay flag usage): - Fix client usage of the MiddleOnly flag so that MiddleOnly relays are not used as HS IP or RP by clients or services. Additionally, give dirauths the ability to remove specific flags, as an - alternative to MiddleOnly. Fixes bug 41023; bugfix on 0.4.7.2-alpha + alternative to MiddleOnly. Fixes bug 41023; bugfix on 0.4.7.2-alpha. o Minor bugfixes (sandbox, bwauth): - Fix sandbox to work for bandwidth authority. Fixes bug 40933; - bugfix on 0.2.2.1-alpha + bugfix on 0.2.2.1-alpha. Changes in version 0.4.8.14 - 2025-02-05 @@ -74,9 +926,142 @@ 40989; bugfix on 0.4.8.13. +Changes in version 0.4.9.1-alpha - 2024-12-03 + This is the first alpha of the 0.4.9.x series. This release mostly consists + of bugfixes including some major ones. There are several minor features in + this release but no large new subsystem. + + o Major bugfixes (sandbox): + - Fix sandbox to work on architectures that use Linux's generic + syscall interface, extending support for AArch64 (ARM64) and + adding support for RISC-V, allowing test_include.sh and the + sandbox unit tests to pass on these systems even when building + with fragile hardening enabled. Fixes bugs 40465 and 40599; bugfix + on 0.2.5.1-alpha. + + o Minor feature (defense in depth): + - Verify needle is smaller than haystack before calling memmem. + Closes ticket 40854. + + o Minor feature (directory authority): + - Introduce MinimalAcceptedServerVersion to allow modification of + minimal accepted version for relays without requiring a new tor + release. Closes ticket 40817. + + o Minor feature (exit policies): + - Implement reevaluating new exit policy against existing + connections. This is controlled by new config option + ReevaluateExitPolicy, defaulting to 0. Closes ticket 40676. + + o Minor feature (exit relay, DoS resistance): + - Implement a token-bucket based rate limiter for stream creation + and resolve request. It is configured by the DoSStream* family of + configuration options. Closes ticket 40736. + + o Minor feature (metrics port): + - New metrics on the MetricsPort for the number of BUG() that + occurred at runtime. Closes MR 760. + + o Minor feature (metrics port, relay): + - Add new metrics for relays on the MetricsPort namely the count of + drop cell, destroy cell and the number of circuit protocol + violation seen that lead to a circuit close. Closes ticket 40816. + + o Minor feature (testing): + - test-network now unconditionally includes IPv6 instead of trying + to detect IPv6 support. + + o Minor feature (testing, CI): + - Use a fixed version of chutney (be881a1e) instead of its current + HEAD. This version should also be preferred when testing locally. + + o Minor features (forward-compatibility): + - We now correctly parse microdescriptors and router descriptors + that do not include TAP onion keys. (For backward compatibility, + authorities continue to require these keys.) Implements part of + proposal 350. + + o Minor features (portability, android): + - Use /data/local/tmp for data storage on Android by default. Closes + ticket 40487. Patch from Hans-Christoph Steiner. + + o Minor features (SOCKS): + - Detect invalid SOCKS5 username/password combinations according to + new extended parameters syntax. (Currently, this rejects any + SOCKS5 username beginning with "", except for the username + "0". Such usernames are now reserved to communicate + additional parameters with other Tor implementations.) Implements + proposal 351. + + o Minor bugfix (MetricsPort, relay): + - Handle rephist tracking of ntor and ntor_v3 handshakes + individually such that MetricsPort exposes the correct values. + Fixes bug 40638; bugfix on 0.4.7.11. + + o Minor bugfix (process): + - Avoid closing all possible FDs when spawning a process (PT). On + some systems, this could lead to 3+ minutes hang. Fixes bug 40990; + bugfix on 0.3.5.1-alpha. + + o Minor bugfix (relay, sandbox): + - Disable a sandbox unit test that is failing on Debian Sid breaking + our nightly packages. Fixes bug 40918; bugfix on 0.3.5.1-alpha. + + o Minor bugfixes (bridge): + - Don't warn when BridgeRelay is 1 and ExitRelay is explicitly set + to 0. Fixes bug 40884; bugfix on 0.4.8.3-rc. + + o Minor bugfixes (compiler warnings): + - Make sure the two bitfields in the half-closed edge struct are + unsigned, as we're using them for boolean values and assign 1 to + them. Fixes bug 40911; bugfix on 0.4.7.2-alpha. + + o Minor bugfixes (conflux, client): + - Avoid a non fatal assert caused by data coming in on a conflux set + that is being freed during shutdown. Fixes bug 40870; bugfix + on 0.4.8.1-alpha. + + o Minor bugfixes (memory): + - Fix a pointer free that wasn't set to NULL afterwards which could + be reused by calling back in the free all function. Fixes bug + 40989; bugfix on 0.4.8.13. + + o Minor bugfixes (sandbox, bwauth): + - Fix sandbox to work for bandwidth authority. Fixes bug 40933; + bugfix on 0.2.2.1-alpha + + o Minor bugfixes (testing): + - Enabling TestingTorNetwork no longer forces fast hidden service + intro point rotation. This reduces noise and errors when using + hidden services with TestingTorNetwork enabled. Fixes bug 40922; + bugfix on 0.3.2.1-alpha. + + o Minor bugfixes (tor-resolve): + - Create socket with correct family as given by sockshost, fixes + IPv6. Fixes bug 40982; bugfix on 0.4.9.0-alpha. + + o Removed features: + - Directory authorities no longer support consensus methods before + method 32. Closes ticket 40835. + + o Removed features (directory authority): + - We include a new consensus method that removes support for + computing "package" lines in consensus documents. This feature was + never used, and support for including it in our votes was removed + in 0.4.2.1-alpha. Finishes implementation of proposal 301. + + o Removed features (obsolete): + - Relays no longer support the obsolete TAP circuit extension + protocol. (For backward compatibility, however, relays still + continue to include TAP keys in their descriptors.) Implements + part of proposal 350. + - Removed some vestigial code for selecting the TAP circuit + extension protocol. + + Changes in version 0.4.8.13 - 2024-10-24 - This is minor release fixing an important client circuit building (Conflux - related) bug which lead to performance degradation and extra load on the + This minor release fixes an important client circuit building (conflux + related) bug which led to performance degradation and extra load on the network. Some minor memory leaks fixes as well as an important minor feature for pluggable transports. We strongly recommend to update as soon as possible for clients in order to neutralize this conflux bug. @@ -89,7 +1074,7 @@ which added overall load to the network, used bandwidth and battery from clients that weren't actively using their Tor, and kept sockets open on guards which added connection padding - essentially forever. Fixes bug 40981; bugfix on 0.4.8.1-alpha; + essentially forever. Fixes bug 40981; bugfix on 0.4.8.1-alpha. o Minor feature (bridges, pluggable transport): - Add STATUS TYPE=version handler for Pluggable Transport. This @@ -143,11 +1128,11 @@ Changes in version 0.4.8.11 - 2024-04-10 - This is a minor release mostly to upgrade the fallbackdir list. Worth noting - also that directory authority running this version will now automatically + This is a minor release mostly to upgrade the fallbackdir list. + Directory authorities running this version will now automatically reject relays running the end of life 0.4.7.x version. - o Minor feature (authority): + o Minor features (directory authorities): - Reject 0.4.7.x series at the authority level. Closes ticket 40896. o Minor feature (dirauth, tor26): @@ -180,7 +1165,7 @@ o Major bugfixes (TROVE-2023-007, exit): - Improper error propagation from a safety check in conflux leg - linking lead to a desynchronization of which legs were part of a + linking led to a desynchronization of which legs were part of a conflux set, ultimately causing a UAF and NULL pointer dereference crash on Exit relays. Fixes bug 40897; bugfix on 0.4.8.1-alpha. @@ -192,8 +1177,8 @@ retrieved on 2023/12/08. o Minor bugfixes (bridges, statistics): - - Correctly report statistics for client count over Pluggable - transport. Fixes bug 40871; bugfix on 0.4.8.4 + - Correctly report statistics for client count over pluggable + transports. Fixes bug 40871; bugfix on 0.4.8.4. Changes in version 0.4.8.9 - 2023-11-09 @@ -215,7 +1200,7 @@ o Major bugfixes (onion service, TROVE-2023-006): - Fix a possible hard assert on a NULL pointer when recording a failed rendezvous circuit on the service side for the MetricsPort. - Fixes bug 40883; bugfix on 0.4.8.1-alpha + Fixes bug 40883; bugfix on 0.4.8.1-alpha. o Minor features (fallbackdir): - Regenerate fallback directories generated on November 09, 2023. @@ -228,7 +1213,7 @@ Changes in version 0.4.8.8 - 2023-11-03 We are releasing today a fix for a high security issue, TROVE-2023-004, that is affecting relays. Also a few minor bugfixes detailed below. Please upgrade - as soon as posssible. + as soon as possible. o Major bugfixes (TROVE-2023-004, relay): - Mitigate an issue when Tor compiled with OpenSSL can crash during @@ -271,11 +1256,10 @@ Changes in version 0.4.8.6 - 2023-09-18 - This version contains an important fix for onion service regarding congestion - control and its reliability. Apart from that, uneeded BUG warnings have been - suppressed especially about a compression bomb seen on relays. We strongly - recommend, in particular onion service operators, to upgrade as soon as - possible to this latest stable. + This version contains an important fix for onion services regarding + congestion control and its reliability. Apart from that, unneeded BUG + warnings have been suppressed especially about a compression bomb seen + on relays. o Major bugfixes (onion service): - Fix a reliability issue where services were expiring their @@ -468,7 +1452,7 @@ o Minor bugfixes (conflux): - Count leg launch attempts prior to attempting to launch them. This - avoids inifinite launch attempts due to internal circuit building + avoids infinite launch attempts due to internal circuit building failures. Additionally, double-check that we have enough exits in our consensus overall, before attempting to launch conflux sets. Fixes bug 40811; bugfix on 0.4.8.1-alpha. @@ -674,7 +1658,7 @@ o Major bugfixes (congestion control): - Avoid incrementing the congestion window when the window is not - fully in use. Thia prevents overshoot in cases where long periods + fully in use. This prevents overshoot in cases where long periods of low activity would allow our congestion window to grow, and then get followed by a burst, which would cause queue overload. Also improve the increment checks for RFC3742. Fixes bug 40732; diff -Nru tor-0.4.8.16/LICENSE tor-0.4.9.6/LICENSE --- tor-0.4.8.16/LICENSE 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/LICENSE 2026-03-25 14:30:34.000000000 +0000 @@ -383,6 +383,33 @@ or promote products derived from this Software. =============================================================================== +Parts of src/ext/polyval are based on Thomas Pornin's GHASH implementation in +BearSSL, and distributed under the following license: + + Copyright (c) 2016 Thomas Pornin + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + +=============================================================================== If you got Tor as a static binary with OpenSSL included, then you should know: "This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)" diff -Nru tor-0.4.8.16/Makefile.am tor-0.4.9.6/Makefile.am --- tor-0.4.8.16/Makefile.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/Makefile.am 2026-03-25 14:30:34.000000000 +0000 @@ -50,12 +50,12 @@ src/lib/libtor-sandbox.a \ src/lib/libtor-container.a \ src/lib/libtor-net.a \ - src/lib/libtor-thread.a \ src/lib/libtor-memarea.a \ src/lib/libtor-math.a \ src/lib/libtor-meminfo.a \ src/lib/libtor-osinfo.a \ src/lib/libtor-log.a \ + src/lib/libtor-thread.a \ src/lib/libtor-lock.a \ src/lib/libtor-fdio.a \ src/lib/libtor-string.a \ @@ -86,13 +86,13 @@ src/lib/libtor-sandbox-testing.a \ src/lib/libtor-container-testing.a \ src/lib/libtor-net-testing.a \ - src/lib/libtor-thread-testing.a \ src/lib/libtor-memarea-testing.a \ src/lib/libtor-math-testing.a \ src/lib/libtor-meminfo-testing.a \ src/lib/libtor-osinfo-testing.a \ src/lib/libtor-term-testing.a \ src/lib/libtor-log-testing.a \ + src/lib/libtor-thread-testing.a \ src/lib/libtor-lock-testing.a \ src/lib/libtor-fdio-testing.a \ src/lib/libtor-string-testing.a \ @@ -112,7 +112,8 @@ src/lib/libtor-tls.a \ src/lib/libtor-crypt-ops.a \ $(LIBKECCAK_TINY) \ - $(LIBDONNA) + $(LIBDONNA) \ + $(LIBPOLYVAL) if BUILD_MODULE_POW TOR_CRYPTO_LIBS += $(EQUIX_LIBS) @@ -126,6 +127,7 @@ src/lib/libtor-crypt-ops-testing.a \ $(LIBKECCAK_TINY) \ $(LIBDONNA) \ + $(LIBPOLYVAL) \ $(EQUIX_LIBS) endif diff -Nru tor-0.4.8.16/Makefile.in tor-0.4.9.6/Makefile.in --- tor-0.4.8.16/Makefile.in 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/Makefile.in 2026-03-25 14:30:34.000000000 +0000 @@ -221,11 +221,11 @@ @UNITTESTS_ENABLED_TRUE@am__append_60 = src/core/libtor-app-testing.a @USE_TRACING_INSTRUMENTATION_LTTNG_TRUE@am__append_61 = \ -@USE_TRACING_INSTRUMENTATION_LTTNG_TRUE@ src/core/or/trace_probes_cc.c \ +@USE_TRACING_INSTRUMENTATION_LTTNG_TRUE@ src/core/or/trace_probes_cc.c \ @USE_TRACING_INSTRUMENTATION_LTTNG_TRUE@ src/core/or/trace_probes_circuit.c @USE_TRACING_INSTRUMENTATION_LTTNG_TRUE@am__append_62 = \ -@USE_TRACING_INSTRUMENTATION_LTTNG_TRUE@ src/core/or/trace_probes_cc.h \ +@USE_TRACING_INSTRUMENTATION_LTTNG_TRUE@ src/core/or/trace_probes_cc.h \ @USE_TRACING_INSTRUMENTATION_LTTNG_TRUE@ src/core/or/trace_probes_circuit.h @BUILD_MODULE_DIRAUTH_TRUE@am__append_63 = $(MODULE_DIRAUTH_SOURCES) @@ -257,7 +257,7 @@ @COVERAGE_ENABLED_FALSE@@USEPYTHON_TRUE@am__append_74 = src/test/test_rebind.sh \ @COVERAGE_ENABLED_FALSE@@USEPYTHON_TRUE@ src/test/test_include.sh @USE_PERL_TRUE@am__append_75 = \ -@USE_PERL_TRUE@ scripts/maint/checkSpaceTest.sh +@USE_PERL_TRUE@ scripts/maint/checkSpaceTest.sh @UNITTESTS_ENABLED_TRUE@am__append_76 = \ @UNITTESTS_ENABLED_TRUE@ src/test/test \ @@ -317,6 +317,7 @@ @UNITTESTS_ENABLED_TRUE@ src/test/test_crypto.c \ @UNITTESTS_ENABLED_TRUE@ src/test/test_crypto_ope.c \ @UNITTESTS_ENABLED_TRUE@ src/test/test_crypto_rng.c \ +@UNITTESTS_ENABLED_TRUE@ src/test/test_crypto_cgo.c \ @UNITTESTS_ENABLED_TRUE@ src/test/test_data.c \ @UNITTESTS_ENABLED_TRUE@ src/test/test_dir.c \ @UNITTESTS_ENABLED_TRUE@ src/test/test_dirauth_ports.c \ @@ -519,9 +520,11 @@ am__src_core_libtor_app_testing_a_SOURCES_DIST = \ src/core/crypto/hs_ntor.c src/core/crypto/onion_crypto.c \ src/core/crypto/onion_fast.c src/core/crypto/onion_ntor.c \ - src/core/crypto/onion_ntor_v3.c src/core/crypto/onion_tap.c \ - src/core/crypto/relay_crypto.c src/core/mainloop/connection.c \ - src/core/mainloop/cpuworker.c src/core/mainloop/mainloop.c \ + src/core/crypto/onion_ntor_v3.c src/core/crypto/relay_crypto.c \ + src/core/crypto/relay_crypto_cgo.c \ + src/core/crypto/relay_crypto_tor1.c \ + src/core/mainloop/connection.c src/core/mainloop/cpuworker.c \ + src/core/mainloop/mainloop.c \ src/core/mainloop/mainloop_pubsub.c \ src/core/mainloop/mainloop_sys.c src/core/mainloop/netstatus.c \ src/core/mainloop/periodic.c src/core/or/address_set.c \ @@ -539,9 +542,10 @@ src/core/or/or_periodic.c src/core/or/or_sys.c \ src/core/or/orconn_event.c src/core/or/policies.c \ src/core/or/protover.c src/core/or/reasons.c \ - src/core/or/relay.c src/core/or/scheduler.c \ - src/core/or/scheduler_kist.c src/core/or/scheduler_vanilla.c \ - src/core/or/sendme.c src/core/or/congestion_control_common.c \ + src/core/or/relay.c src/core/or/relay_msg.c \ + src/core/or/scheduler.c src/core/or/scheduler_kist.c \ + src/core/or/scheduler_vanilla.c src/core/or/sendme.c \ + src/core/or/congestion_control_common.c \ src/core/or/congestion_control_vegas.c \ src/core/or/congestion_control_flow.c src/core/or/conflux.c \ src/core/or/conflux_cell.c src/core/or/conflux_params.c \ @@ -701,8 +705,9 @@ src/core/crypto/libtor_app_testing_a-onion_fast.$(OBJEXT) \ src/core/crypto/libtor_app_testing_a-onion_ntor.$(OBJEXT) \ src/core/crypto/libtor_app_testing_a-onion_ntor_v3.$(OBJEXT) \ - src/core/crypto/libtor_app_testing_a-onion_tap.$(OBJEXT) \ src/core/crypto/libtor_app_testing_a-relay_crypto.$(OBJEXT) \ + src/core/crypto/libtor_app_testing_a-relay_crypto_cgo.$(OBJEXT) \ + src/core/crypto/libtor_app_testing_a-relay_crypto_tor1.$(OBJEXT) \ src/core/mainloop/libtor_app_testing_a-connection.$(OBJEXT) \ src/core/mainloop/libtor_app_testing_a-cpuworker.$(OBJEXT) \ src/core/mainloop/libtor_app_testing_a-mainloop.$(OBJEXT) \ @@ -739,6 +744,7 @@ src/core/or/libtor_app_testing_a-protover.$(OBJEXT) \ src/core/or/libtor_app_testing_a-reasons.$(OBJEXT) \ src/core/or/libtor_app_testing_a-relay.$(OBJEXT) \ + src/core/or/libtor_app_testing_a-relay_msg.$(OBJEXT) \ src/core/or/libtor_app_testing_a-scheduler.$(OBJEXT) \ src/core/or/libtor_app_testing_a-scheduler_kist.$(OBJEXT) \ src/core/or/libtor_app_testing_a-scheduler_vanilla.$(OBJEXT) \ @@ -873,7 +879,9 @@ am__src_core_libtor_app_a_SOURCES_DIST = src/core/crypto/hs_ntor.c \ src/core/crypto/onion_crypto.c src/core/crypto/onion_fast.c \ src/core/crypto/onion_ntor.c src/core/crypto/onion_ntor_v3.c \ - src/core/crypto/onion_tap.c src/core/crypto/relay_crypto.c \ + src/core/crypto/relay_crypto.c \ + src/core/crypto/relay_crypto_cgo.c \ + src/core/crypto/relay_crypto_tor1.c \ src/core/mainloop/connection.c src/core/mainloop/cpuworker.c \ src/core/mainloop/mainloop.c \ src/core/mainloop/mainloop_pubsub.c \ @@ -893,9 +901,10 @@ src/core/or/or_periodic.c src/core/or/or_sys.c \ src/core/or/orconn_event.c src/core/or/policies.c \ src/core/or/protover.c src/core/or/reasons.c \ - src/core/or/relay.c src/core/or/scheduler.c \ - src/core/or/scheduler_kist.c src/core/or/scheduler_vanilla.c \ - src/core/or/sendme.c src/core/or/congestion_control_common.c \ + src/core/or/relay.c src/core/or/relay_msg.c \ + src/core/or/scheduler.c src/core/or/scheduler_kist.c \ + src/core/or/scheduler_vanilla.c src/core/or/sendme.c \ + src/core/or/congestion_control_common.c \ src/core/or/congestion_control_vegas.c \ src/core/or/congestion_control_flow.c src/core/or/conflux.c \ src/core/or/conflux_cell.c src/core/or/conflux_params.c \ @@ -1055,8 +1064,9 @@ src/core/crypto/onion_fast.$(OBJEXT) \ src/core/crypto/onion_ntor.$(OBJEXT) \ src/core/crypto/onion_ntor_v3.$(OBJEXT) \ - src/core/crypto/onion_tap.$(OBJEXT) \ src/core/crypto/relay_crypto.$(OBJEXT) \ + src/core/crypto/relay_crypto_cgo.$(OBJEXT) \ + src/core/crypto/relay_crypto_tor1.$(OBJEXT) \ src/core/mainloop/connection.$(OBJEXT) \ src/core/mainloop/cpuworker.$(OBJEXT) \ src/core/mainloop/mainloop.$(OBJEXT) \ @@ -1086,6 +1096,7 @@ src/core/or/orconn_event.$(OBJEXT) \ src/core/or/policies.$(OBJEXT) src/core/or/protover.$(OBJEXT) \ src/core/or/reasons.$(OBJEXT) src/core/or/relay.$(OBJEXT) \ + src/core/or/relay_msg.$(OBJEXT) \ src/core/or/scheduler.$(OBJEXT) \ src/core/or/scheduler_kist.$(OBJEXT) \ src/core/or/scheduler_vanilla.$(OBJEXT) \ @@ -1288,6 +1299,12 @@ @BUILD_KECCAK_TINY_TRUE@am_src_ext_keccak_tiny_libkeccak_tiny_a_OBJECTS = src/ext/keccak-tiny/libkeccak_tiny_a-keccak-tiny-unrolled.$(OBJEXT) src_ext_keccak_tiny_libkeccak_tiny_a_OBJECTS = \ $(am_src_ext_keccak_tiny_libkeccak_tiny_a_OBJECTS) +src_ext_polyval_libpolyval_a_AR = $(AR) $(ARFLAGS) +src_ext_polyval_libpolyval_a_LIBADD = +am_src_ext_polyval_libpolyval_a_OBJECTS = \ + src/ext/polyval/libpolyval_a-polyval.$(OBJEXT) +src_ext_polyval_libpolyval_a_OBJECTS = \ + $(am_src_ext_polyval_libpolyval_a_OBJECTS) src_lib_libcurve25519_donna_a_AR = $(AR) $(ARFLAGS) src_lib_libcurve25519_donna_a_LIBADD = am__src_lib_libcurve25519_donna_a_SOURCES_DIST = \ @@ -2249,7 +2266,7 @@ src/trunnel/sendme_cell.c src/trunnel/flow_control_cells.c \ src/trunnel/congestion_control.c src/trunnel/socks5.c \ src/trunnel/netinfo.c src/trunnel/circpad_negotiation.c \ - src/trunnel/conflux.c + src/trunnel/conflux.c src/trunnel/subproto_request.c am__objects_107 = src/ext/trunnel/trunnel_libor_trunnel_testing_a-trunnel.$(OBJEXT) \ src/trunnel/libor_trunnel_testing_a-ed25519_cert.$(OBJEXT) \ src/trunnel/libor_trunnel_testing_a-extension.$(OBJEXT) \ @@ -2265,7 +2282,8 @@ src/trunnel/libor_trunnel_testing_a-socks5.$(OBJEXT) \ src/trunnel/libor_trunnel_testing_a-netinfo.$(OBJEXT) \ src/trunnel/libor_trunnel_testing_a-circpad_negotiation.$(OBJEXT) \ - src/trunnel/libor_trunnel_testing_a-conflux.$(OBJEXT) + src/trunnel/libor_trunnel_testing_a-conflux.$(OBJEXT) \ + src/trunnel/libor_trunnel_testing_a-subproto_request.$(OBJEXT) @UNITTESTS_ENABLED_TRUE@am_src_trunnel_libor_trunnel_testing_a_OBJECTS = \ @UNITTESTS_ENABLED_TRUE@ $(am__objects_107) src_trunnel_libor_trunnel_testing_a_OBJECTS = \ @@ -2288,7 +2306,8 @@ src/trunnel/libor_trunnel_a-socks5.$(OBJEXT) \ src/trunnel/libor_trunnel_a-netinfo.$(OBJEXT) \ src/trunnel/libor_trunnel_a-circpad_negotiation.$(OBJEXT) \ - src/trunnel/libor_trunnel_a-conflux.$(OBJEXT) + src/trunnel/libor_trunnel_a-conflux.$(OBJEXT) \ + src/trunnel/libor_trunnel_a-subproto_request.$(OBJEXT) am_src_trunnel_libor_trunnel_a_OBJECTS = $(am__objects_108) src_trunnel_libor_trunnel_a_OBJECTS = \ $(am_src_trunnel_libor_trunnel_a_OBJECTS) @@ -2697,51 +2716,52 @@ src/test/test_containers.c src/test/test_controller.c \ src/test/test_controller_events.c src/test/test_crypto.c \ src/test/test_crypto_ope.c src/test/test_crypto_rng.c \ - src/test/test_data.c src/test/test_dir.c \ - src/test/test_dirauth_ports.c src/test/test_dirvote.c \ - src/test/test_dir_common.c src/test/test_dir_handle_get.c \ - src/test/test_dispatch.c src/test/test_dos.c \ - src/test/test_entryconn.c src/test/test_entrynodes.c \ - src/test/test_geoip.c src/test/test_guardfraction.c \ - src/test/test_extorport.c src/test/test_hs_common.c \ - src/test/test_hs_config.c src/test/test_hs_cell.c \ - src/test/test_hs_ntor.c src/test/test_hs_service.c \ - src/test/test_hs_client.c src/test/test_hs_intropoint.c \ - src/test/test_hs_control.c src/test/test_hs_ob.c \ - src/test/test_handles.c src/test/test_hs_cache.c \ - src/test/test_hs_descriptor.c src/test/test_hs_dos.c \ - src/test/test_hs_metrics.c src/test/test_hs_pow.c \ - src/test/test_keypin.c src/test/test_link_handshake.c \ - src/test/test_logging.c src/test/test_mainloop.c \ - src/test/test_metrics.c src/test/test_microdesc.c \ - src/test/test_namemap.c src/test/test_netinfo.c \ - src/test/test_nodelist.c src/test/test_ntor_v3.c \ - src/test/test_oom.c src/test/test_oos.c \ - src/test/test_options.c src/test/test_options_act.c \ - src/test/test_pem.c src/test/test_periodic_event.c \ - src/test/test_policy.c src/test/test_process.c \ - src/test/test_process_descs.c src/test/test_prob_distr.c \ - src/test/test_procmon.c src/test/test_proto_haproxy.c \ - src/test/test_proto_http.c src/test/test_proto_misc.c \ - src/test/test_protover.c src/test/test_pt.c \ - src/test/test_pubsub_build.c src/test/test_pubsub_msg.c \ - src/test/test_relay.c src/test/test_relaycell.c \ - src/test/test_relaycrypt.c src/test/test_replay.c \ - src/test/test_router.c src/test/test_routerkeys.c \ - src/test/test_routerlist.c src/test/test_routerset.c \ - src/test/test_sandbox.c src/test/test_scheduler.c \ - src/test/test_sendme.c src/test/test_shared_random.c \ - src/test/test_socks.c src/test/test_statefile.c \ - src/test/test_stats.c src/test/test_status.c \ - src/test/test_storagedir.c src/test/test_threads.c \ - src/test/test_token_bucket.c src/test/test_tortls.c \ - src/test/test_util.c src/test/test_util_format.c \ - src/test/test_util_process.c src/test/test_voting_flags.c \ - src/test/test_voting_schedule.c src/test/test_x509.c \ - src/test/test_helpers.c src/test/test_dns.c \ - src/test/test_parsecommon.c src/test/testing_common.c \ - src/test/testing_rsakeys.c src/ext/tinytest.c \ - src/test/test_crypto_openssl.c src/test/test_tortls_openssl.c + src/test/test_crypto_cgo.c src/test/test_data.c \ + src/test/test_dir.c src/test/test_dirauth_ports.c \ + src/test/test_dirvote.c src/test/test_dir_common.c \ + src/test/test_dir_handle_get.c src/test/test_dispatch.c \ + src/test/test_dos.c src/test/test_entryconn.c \ + src/test/test_entrynodes.c src/test/test_geoip.c \ + src/test/test_guardfraction.c src/test/test_extorport.c \ + src/test/test_hs_common.c src/test/test_hs_config.c \ + src/test/test_hs_cell.c src/test/test_hs_ntor.c \ + src/test/test_hs_service.c src/test/test_hs_client.c \ + src/test/test_hs_intropoint.c src/test/test_hs_control.c \ + src/test/test_hs_ob.c src/test/test_handles.c \ + src/test/test_hs_cache.c src/test/test_hs_descriptor.c \ + src/test/test_hs_dos.c src/test/test_hs_metrics.c \ + src/test/test_hs_pow.c src/test/test_keypin.c \ + src/test/test_link_handshake.c src/test/test_logging.c \ + src/test/test_mainloop.c src/test/test_metrics.c \ + src/test/test_microdesc.c src/test/test_namemap.c \ + src/test/test_netinfo.c src/test/test_nodelist.c \ + src/test/test_ntor_v3.c src/test/test_oom.c \ + src/test/test_oos.c src/test/test_options.c \ + src/test/test_options_act.c src/test/test_pem.c \ + src/test/test_periodic_event.c src/test/test_policy.c \ + src/test/test_process.c src/test/test_process_descs.c \ + src/test/test_prob_distr.c src/test/test_procmon.c \ + src/test/test_proto_haproxy.c src/test/test_proto_http.c \ + src/test/test_proto_misc.c src/test/test_protover.c \ + src/test/test_pt.c src/test/test_pubsub_build.c \ + src/test/test_pubsub_msg.c src/test/test_relay.c \ + src/test/test_relaycell.c src/test/test_relaycrypt.c \ + src/test/test_replay.c src/test/test_router.c \ + src/test/test_routerkeys.c src/test/test_routerlist.c \ + src/test/test_routerset.c src/test/test_sandbox.c \ + src/test/test_scheduler.c src/test/test_sendme.c \ + src/test/test_shared_random.c src/test/test_socks.c \ + src/test/test_statefile.c src/test/test_stats.c \ + src/test/test_status.c src/test/test_storagedir.c \ + src/test/test_threads.c src/test/test_token_bucket.c \ + src/test/test_tortls.c src/test/test_util.c \ + src/test/test_util_format.c src/test/test_util_process.c \ + src/test/test_voting_flags.c src/test/test_voting_schedule.c \ + src/test/test_x509.c src/test/test_helpers.c \ + src/test/test_dns.c src/test/test_parsecommon.c \ + src/test/testing_common.c src/test/testing_rsakeys.c \ + src/ext/tinytest.c src/test/test_crypto_openssl.c \ + src/test/test_tortls_openssl.c @UNITTESTS_ENABLED_TRUE@am__objects_126 = \ @UNITTESTS_ENABLED_TRUE@ src/test/test-fakecircs.$(OBJEXT) \ @UNITTESTS_ENABLED_TRUE@ src/test/test-log_test_helpers.$(OBJEXT) \ @@ -2788,6 +2808,7 @@ @UNITTESTS_ENABLED_TRUE@ src/test/test-test_crypto.$(OBJEXT) \ @UNITTESTS_ENABLED_TRUE@ src/test/test-test_crypto_ope.$(OBJEXT) \ @UNITTESTS_ENABLED_TRUE@ src/test/test-test_crypto_rng.$(OBJEXT) \ +@UNITTESTS_ENABLED_TRUE@ src/test/test-test_crypto_cgo.$(OBJEXT) \ @UNITTESTS_ENABLED_TRUE@ src/test/test-test_data.$(OBJEXT) \ @UNITTESTS_ENABLED_TRUE@ src/test/test-test_dir.$(OBJEXT) \ @UNITTESTS_ENABLED_TRUE@ src/test/test-test_dirauth_ports.$(OBJEXT) \ @@ -3082,14 +3103,16 @@ src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_fast.Po \ src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_ntor.Po \ src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_ntor_v3.Po \ - src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_tap.Po \ src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto.Po \ + src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_cgo.Po \ + src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_tor1.Po \ src/core/crypto/$(DEPDIR)/onion_crypto.Po \ src/core/crypto/$(DEPDIR)/onion_fast.Po \ src/core/crypto/$(DEPDIR)/onion_ntor.Po \ src/core/crypto/$(DEPDIR)/onion_ntor_v3.Po \ - src/core/crypto/$(DEPDIR)/onion_tap.Po \ src/core/crypto/$(DEPDIR)/relay_crypto.Po \ + src/core/crypto/$(DEPDIR)/relay_crypto_cgo.Po \ + src/core/crypto/$(DEPDIR)/relay_crypto_tor1.Po \ src/core/mainloop/$(DEPDIR)/connection.Po \ src/core/mainloop/$(DEPDIR)/cpuworker.Po \ src/core/mainloop/$(DEPDIR)/libtor_app_testing_a-connection.Po \ @@ -3171,6 +3194,7 @@ src/core/or/$(DEPDIR)/libtor_app_testing_a-protover.Po \ src/core/or/$(DEPDIR)/libtor_app_testing_a-reasons.Po \ src/core/or/$(DEPDIR)/libtor_app_testing_a-relay.Po \ + src/core/or/$(DEPDIR)/libtor_app_testing_a-relay_msg.Po \ src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler.Po \ src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler_kist.Po \ src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler_vanilla.Po \ @@ -3188,6 +3212,7 @@ src/core/or/$(DEPDIR)/protover.Po \ src/core/or/$(DEPDIR)/reasons.Po \ src/core/or/$(DEPDIR)/relay.Po \ + src/core/or/$(DEPDIR)/relay_msg.Po \ src/core/or/$(DEPDIR)/scheduler.Po \ src/core/or/$(DEPDIR)/scheduler_kist.Po \ src/core/or/$(DEPDIR)/scheduler_vanilla.Po \ @@ -3277,6 +3302,7 @@ src/ext/keccak-tiny/$(DEPDIR)/libkeccak_tiny_a-keccak-tiny-unrolled.Po \ src/ext/mulodi/$(DEPDIR)/lib_libtor_ctime_a-mulodi4.Po \ src/ext/mulodi/$(DEPDIR)/lib_libtor_ctime_testing_a-mulodi4.Po \ + src/ext/polyval/$(DEPDIR)/libpolyval_a-polyval.Po \ src/ext/trunnel/$(DEPDIR)/trunnel_libor_trunnel_a-trunnel.Po \ src/ext/trunnel/$(DEPDIR)/trunnel_libor_trunnel_testing_a-trunnel.Po \ src/feature/api/$(DEPDIR)/core_libtor_app_testing_a-tor_api.Po \ @@ -3881,6 +3907,7 @@ src/test/$(DEPDIR)/test-test_controller.Po \ src/test/$(DEPDIR)/test-test_controller_events.Po \ src/test/$(DEPDIR)/test-test_crypto.Po \ + src/test/$(DEPDIR)/test-test_crypto_cgo.Po \ src/test/$(DEPDIR)/test-test_crypto_ope.Po \ src/test/$(DEPDIR)/test-test_crypto_openssl.Po \ src/test/$(DEPDIR)/test-test_crypto_rng.Po \ @@ -4104,6 +4131,7 @@ src/trunnel/$(DEPDIR)/libor_trunnel_a-pwbox.Po \ src/trunnel/$(DEPDIR)/libor_trunnel_a-sendme_cell.Po \ src/trunnel/$(DEPDIR)/libor_trunnel_a-socks5.Po \ + src/trunnel/$(DEPDIR)/libor_trunnel_a-subproto_request.Po \ src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-channelpadding_negotiation.Po \ src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-circpad_negotiation.Po \ src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-conflux.Po \ @@ -4116,6 +4144,7 @@ src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-pwbox.Po \ src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-sendme_cell.Po \ src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-socks5.Po \ + src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-subproto_request.Po \ src/trunnel/hs/$(DEPDIR)/libor_trunnel_a-cell_establish_intro.Po \ src/trunnel/hs/$(DEPDIR)/libor_trunnel_a-cell_introduce1.Po \ src/trunnel/hs/$(DEPDIR)/libor_trunnel_a-cell_rendezvous.Po \ @@ -4146,6 +4175,7 @@ $(src_ext_equix_libequix_a_SOURCES) \ $(src_ext_equix_libhashx_a_SOURCES) \ $(src_ext_keccak_tiny_libkeccak_tiny_a_SOURCES) \ + $(src_ext_polyval_libpolyval_a_SOURCES) \ $(src_lib_libcurve25519_donna_a_SOURCES) \ $(src_lib_libtor_buf_testing_a_SOURCES) \ $(src_lib_libtor_buf_a_SOURCES) \ @@ -4290,6 +4320,7 @@ $(src_ext_equix_libequix_a_SOURCES) \ $(src_ext_equix_libhashx_a_SOURCES) \ $(am__src_ext_keccak_tiny_libkeccak_tiny_a_SOURCES_DIST) \ + $(src_ext_polyval_libpolyval_a_SOURCES) \ $(am__src_lib_libcurve25519_donna_a_SOURCES_DIST) \ $(src_lib_libtor_buf_testing_a_SOURCES) \ $(src_lib_libtor_buf_a_SOURCES) \ @@ -4507,7 +4538,9 @@ src/ext/equix/hashx/src/virtual_memory.h \ src/ext/equix/include/equix.h src/ext/equix/src/context.h \ src/ext/equix/src/solver_heap.h src/ext/equix/src/solver.h \ - src/ext/keccak-tiny/keccak-tiny.h src/lib/arch/bytes.h \ + src/ext/keccak-tiny/keccak-tiny.h src/ext/polyval/polyval.h \ + src/ext/polyval/pclmul.c src/ext/polyval/ctmul64.c \ + src/ext/polyval/ctmul.c src/lib/arch/bytes.h \ src/lib/buf/buffers.h src/lib/err/backtrace.h \ src/lib/err/torerr.h src/lib/err/torerr_sys.h \ src/lib/cc/compat_compiler.h src/lib/cc/ctassert.h \ @@ -4606,16 +4639,17 @@ src/lib/thread/numcpus.h src/lib/thread/thread_sys.h \ src/lib/thread/threads.h src/lib/time/compat_time.h \ src/lib/time/time_sys.h src/lib/time/tvdiff.h \ - src/lib/tls/ciphers.inc src/lib/tls/buffers_tls.h \ - src/lib/tls/nss_countbytes.h src/lib/tls/tortls.h \ - src/lib/tls/tortls_internal.h src/lib/tls/tortls_st.h \ - src/lib/tls/tortls_sys.h src/lib/tls/x509.h \ - src/lib/tls/x509_internal.h src/lib/trace/trace.h \ - src/lib/trace/trace_sys.h src/lib/trace/events.h \ - src/lib/trace/debug.h src/lib/trace/usdt/usdt.h \ - src/lib/trace/lttng/lttng.h src/lib/version/git_revision.h \ - src/lib/version/torversion.h src/lib/wallclock/approx_time.h \ - src/lib/wallclock/timeval.h src/lib/wallclock/time_to_tm.h \ + src/lib/tls/ciphers.inc src/lib/tls/ciphers_v13.inc \ + src/lib/tls/buffers_tls.h src/lib/tls/nss_countbytes.h \ + src/lib/tls/tortls.h src/lib/tls/tortls_internal.h \ + src/lib/tls/tortls_st.h src/lib/tls/tortls_sys.h \ + src/lib/tls/x509.h src/lib/tls/x509_internal.h \ + src/lib/trace/trace.h src/lib/trace/trace_sys.h \ + src/lib/trace/events.h src/lib/trace/debug.h \ + src/lib/trace/usdt/usdt.h src/lib/trace/lttng/lttng.h \ + src/lib/version/git_revision.h src/lib/version/torversion.h \ + src/lib/wallclock/approx_time.h src/lib/wallclock/timeval.h \ + src/lib/wallclock/time_to_tm.h \ src/lib/wallclock/tor_gettimeofday.h \ src/lib/wallclock/wallclock_sys.h src/ext/trunnel/trunnel.h \ src/ext/trunnel/trunnel-impl.h src/trunnel/trunnel-local.h \ @@ -4628,12 +4662,15 @@ src/trunnel/sendme_cell.h src/trunnel/flow_control_cells.h \ src/trunnel/congestion_control.h src/trunnel/socks5.h \ src/trunnel/netinfo.h src/trunnel/circpad_negotiation.h \ - src/trunnel/conflux.h src/core/crypto/hs_ntor.h \ - src/core/crypto/onion_crypto.h src/core/crypto/onion_fast.h \ - src/core/crypto/onion_ntor.h src/core/crypto/onion_ntor_v3.h \ - src/core/crypto/onion_tap.h src/core/crypto/relay_crypto.h \ - src/core/mainloop/connection.h src/core/mainloop/cpuworker.h \ - src/core/mainloop/mainloop.h \ + src/trunnel/conflux.h src/trunnel/subproto_request.h \ + src/core/crypto/hs_ntor.h src/core/crypto/onion_crypto.h \ + src/core/crypto/onion_fast.h src/core/crypto/onion_ntor.h \ + src/core/crypto/onion_ntor_v3.h src/core/crypto/relay_crypto.h \ + src/core/crypto/relay_crypto_st.h \ + src/core/crypto/relay_crypto_cgo.h \ + src/core/crypto/relay_crypto_tor1.h \ + src/core/crypto/tor1_crypt_st.h src/core/mainloop/connection.h \ + src/core/mainloop/cpuworker.h src/core/mainloop/mainloop.h \ src/core/mainloop/mainloop_pubsub.h \ src/core/mainloop/mainloop_state.inc \ src/core/mainloop/mainloop_state_st.h \ @@ -4669,8 +4706,9 @@ src/core/or/origin_circuit_st.h src/core/or/policies.h \ src/core/or/port_cfg_st.h src/core/or/protover.h \ src/core/or/reasons.h src/core/or/relay.h \ - src/core/or/relay_crypto_st.h src/core/or/scheduler.h \ - src/core/or/sendme.h src/core/or/congestion_control_flow.h \ + src/core/or/relay_msg.h src/core/or/relay_msg_st.h \ + src/core/or/scheduler.h src/core/or/sendme.h \ + src/core/or/congestion_control_flow.h \ src/core/or/congestion_control_common.h \ src/core/or/congestion_control_vegas.h src/core/or/conflux.h \ src/core/or/conflux_cell.h src/core/or/conflux_params.h \ @@ -4815,17 +4853,18 @@ src/app/config/fallback_dirs.inc src/app/config/testnet.inc \ src/app/main/main.h src/app/main/ntmain.h \ src/app/main/risky_options.h src/app/main/shutdown.h \ - src/app/main/subsysmgr.h src/test/fakechans.h \ - src/test/fakecircs.h src/test/hs_test_helpers.h \ - src/test/log_test_helpers.h src/test/opts_test_helpers.h \ - src/test/resolve_test_helpers.h src/test/rng_test_helpers.h \ - src/test/test.h src/test/ptr_helpers.h src/test/test_helpers.h \ + src/app/main/subsysmgr.h src/test/compression_bomb.h \ + src/test/fakechans.h src/test/fakecircs.h \ + src/test/hs_test_helpers.h src/test/log_test_helpers.h \ + src/test/opts_test_helpers.h src/test/resolve_test_helpers.h \ + src/test/rng_test_helpers.h src/test/test.h \ + src/test/ptr_helpers.h src/test/test_helpers.h \ src/test/test_dir_common.h src/test/test_connection.h \ src/test/test_tortls.h src/test/test_descriptors.inc \ src/test/example_extrainfo.inc \ src/test/failing_routerdescs.inc src/test/ed25519_vectors.inc \ - src/test/test_hs_descriptor.inc src/test/vote_descriptors.inc \ - src/test/fuzz/fuzzing.h + src/test/cgo_vectors.inc src/test/test_hs_descriptor.inc \ + src/test/vote_descriptors.inc src/test/fuzz/fuzzing.h HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)orconfig.h.in @@ -5288,9 +5327,9 @@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 noinst_LIBRARIES = $(LIBED25519_REF10) $(LIBED25519_DONNA) \ - $(EQUIX_LIBS) $(am__append_6) src/lib/libtor-buf.a \ - $(am__append_7) src/lib/libtor-err.a $(am__append_8) \ - src/lib/libtor-ctime.a $(am__append_9) \ + $(EQUIX_LIBS) $(am__append_6) $(LIBPOLYVAL) \ + src/lib/libtor-buf.a $(am__append_7) src/lib/libtor-err.a \ + $(am__append_8) src/lib/libtor-ctime.a $(am__append_9) \ src/lib/libtor-compress.a $(am__append_10) \ src/lib/libtor-confmgt.a $(am__append_11) \ src/lib/libtor-container.a $(am__append_12) \ @@ -5542,7 +5581,7 @@ # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS = $(EXTHEADERS) $(ED25519_REF10_HDRS) \ $(ED25519_DONNA_HDRS) $(EQUIX_HDRS) $(am__append_5) \ - src/lib/arch/bytes.h src/lib/buf/buffers.h \ + $(POLYVAL_HDRS) src/lib/arch/bytes.h src/lib/buf/buffers.h \ src/lib/err/backtrace.h src/lib/err/torerr.h \ src/lib/err/torerr_sys.h src/lib/cc/compat_compiler.h \ src/lib/cc/ctassert.h src/lib/cc/tokpaste.h \ @@ -5640,11 +5679,11 @@ src/lib/thread/numcpus.h src/lib/thread/thread_sys.h \ src/lib/thread/threads.h src/lib/time/compat_time.h \ src/lib/time/time_sys.h src/lib/time/tvdiff.h \ - src/lib/tls/ciphers.inc src/lib/tls/buffers_tls.h \ - src/lib/tls/nss_countbytes.h src/lib/tls/tortls.h \ - src/lib/tls/tortls_internal.h src/lib/tls/tortls_st.h \ - src/lib/tls/tortls_sys.h src/lib/tls/x509.h \ - src/lib/tls/x509_internal.h $(TRACEHEADERS) \ + src/lib/tls/ciphers.inc src/lib/tls/ciphers_v13.inc \ + src/lib/tls/buffers_tls.h src/lib/tls/nss_countbytes.h \ + src/lib/tls/tortls.h src/lib/tls/tortls_internal.h \ + src/lib/tls/tortls_st.h src/lib/tls/tortls_sys.h \ + src/lib/tls/x509.h src/lib/tls/x509_internal.h $(TRACEHEADERS) \ src/lib/version/git_revision.h src/lib/version/torversion.h \ src/lib/wallclock/approx_time.h src/lib/wallclock/timeval.h \ src/lib/wallclock/time_to_tm.h \ @@ -5652,8 +5691,11 @@ src/lib/wallclock/wallclock_sys.h $(TRUNNELHEADERS) \ src/core/crypto/hs_ntor.h src/core/crypto/onion_crypto.h \ src/core/crypto/onion_fast.h src/core/crypto/onion_ntor.h \ - src/core/crypto/onion_ntor_v3.h src/core/crypto/onion_tap.h \ - src/core/crypto/relay_crypto.h src/core/mainloop/connection.h \ + src/core/crypto/onion_ntor_v3.h src/core/crypto/relay_crypto.h \ + src/core/crypto/relay_crypto_st.h \ + src/core/crypto/relay_crypto_cgo.h \ + src/core/crypto/relay_crypto_tor1.h \ + src/core/crypto/tor1_crypt_st.h src/core/mainloop/connection.h \ src/core/mainloop/cpuworker.h src/core/mainloop/mainloop.h \ src/core/mainloop/mainloop_pubsub.h \ src/core/mainloop/mainloop_state.inc \ @@ -5690,8 +5732,9 @@ src/core/or/origin_circuit_st.h src/core/or/policies.h \ src/core/or/port_cfg_st.h src/core/or/protover.h \ src/core/or/reasons.h src/core/or/relay.h \ - src/core/or/relay_crypto_st.h src/core/or/scheduler.h \ - src/core/or/sendme.h src/core/or/congestion_control_flow.h \ + src/core/or/relay_msg.h src/core/or/relay_msg_st.h \ + src/core/or/scheduler.h src/core/or/sendme.h \ + src/core/or/congestion_control_flow.h \ src/core/or/congestion_control_common.h \ src/core/or/congestion_control_vegas.h src/core/or/conflux.h \ src/core/or/conflux_cell.h src/core/or/conflux_params.h \ @@ -5836,17 +5879,18 @@ src/app/main/main.h src/app/main/ntmain.h \ src/app/main/risky_options.h src/app/main/shutdown.h \ src/app/main/subsysmgr.h src/app/main/ntmain.h \ - src/test/fakechans.h src/test/fakecircs.h \ - src/test/hs_test_helpers.h src/test/log_test_helpers.h \ - src/test/opts_test_helpers.h src/test/resolve_test_helpers.h \ - src/test/rng_test_helpers.h src/test/test.h \ - src/test/ptr_helpers.h src/test/test_helpers.h \ + src/test/compression_bomb.h src/test/fakechans.h \ + src/test/fakecircs.h src/test/hs_test_helpers.h \ + src/test/log_test_helpers.h src/test/opts_test_helpers.h \ + src/test/resolve_test_helpers.h src/test/rng_test_helpers.h \ + src/test/test.h src/test/ptr_helpers.h src/test/test_helpers.h \ src/test/test_dir_common.h src/test/test_connection.h \ src/test/test_tortls.h src/test/test_descriptors.inc \ src/test/example_extrainfo.inc \ src/test/failing_routerdescs.inc src/test/ed25519_vectors.inc \ - src/test/test_descriptors.inc src/test/test_hs_descriptor.inc \ - src/test/vote_descriptors.inc src/test/fuzz/fuzzing.h + src/test/cgo_vectors.inc src/test/test_descriptors.inc \ + src/test/test_hs_descriptor.inc src/test/vote_descriptors.inc \ + src/test/fuzz/fuzzing.h CLEANFILES = micro-revision.i micro-revision.tmp $(asciidoc_product) DISTCLEANFILES = $(html_in) $(man_in) MOSTLYCLEANFILES = libtor.a $(am__append_2) @@ -5880,12 +5924,12 @@ src/lib/libtor-sandbox.a \ src/lib/libtor-container.a \ src/lib/libtor-net.a \ - src/lib/libtor-thread.a \ src/lib/libtor-memarea.a \ src/lib/libtor-math.a \ src/lib/libtor-meminfo.a \ src/lib/libtor-osinfo.a \ src/lib/libtor-log.a \ + src/lib/libtor-thread.a \ src/lib/libtor-lock.a \ src/lib/libtor-fdio.a \ src/lib/libtor-string.a \ @@ -5916,13 +5960,13 @@ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-sandbox-testing.a \ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-container-testing.a \ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-net-testing.a \ -@UNITTESTS_ENABLED_TRUE@ src/lib/libtor-thread-testing.a \ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-memarea-testing.a \ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-math-testing.a \ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-meminfo-testing.a \ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-osinfo-testing.a \ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-term-testing.a \ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-log-testing.a \ +@UNITTESTS_ENABLED_TRUE@ src/lib/libtor-thread-testing.a \ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-lock-testing.a \ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-fdio-testing.a \ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-string-testing.a \ @@ -5939,7 +5983,7 @@ # Internal crypto libraries used in Tor TOR_CRYPTO_LIBS = src/lib/libtor-tls.a src/lib/libtor-crypt-ops.a \ - $(LIBKECCAK_TINY) $(LIBDONNA) $(am__append_1) + $(LIBKECCAK_TINY) $(LIBDONNA) $(LIBPOLYVAL) $(am__append_1) # Variants of the above for linking the testing variant of tor (for coverage # and tests) @@ -5948,6 +5992,7 @@ @UNITTESTS_ENABLED_TRUE@ src/lib/libtor-crypt-ops-testing.a \ @UNITTESTS_ENABLED_TRUE@ $(LIBKECCAK_TINY) \ @UNITTESTS_ENABLED_TRUE@ $(LIBDONNA) \ +@UNITTESTS_ENABLED_TRUE@ $(LIBPOLYVAL) \ @UNITTESTS_ENABLED_TRUE@ $(EQUIX_LIBS) @@ -5977,15 +6022,15 @@ TOR_LIBS_CRYPTLIB = @TOR_OPENSSL_LIBS@ $(am__append_4) TOR_CFLAGS_CRYPTLIB = $(am__append_3) EXTHEADERS = \ - src/ext/ht.h \ - src/ext/byteorder.h \ - src/ext/tinytest.h \ + src/ext/ht.h \ + src/ext/byteorder.h \ + src/ext/tinytest.h \ src/ext/tor_readpassphrase.h \ - src/ext/strlcat.c \ - src/ext/strlcpy.c \ - src/ext/getdelim.c \ + src/ext/strlcat.c \ + src/ext/strlcpy.c \ + src/ext/getdelim.c \ src/ext/tinytest_macros.h \ - src/ext/tor_queue.h \ + src/ext/tor_queue.h \ src/ext/siphash.h \ src/ext/compat_blake2.h \ src/ext/timeouts/timeout.h \ @@ -6168,6 +6213,19 @@ @BUILD_KECCAK_TINY_TRUE@ src/ext/keccak-tiny/keccak-tiny.h @BUILD_KECCAK_TINY_TRUE@LIBKECCAK_TINY = src/ext/keccak-tiny/libkeccak-tiny.a +src_ext_polyval_libpolyval_a_CFLAGS = \ + @CFLAGS_CONSTTIME@ + +src_ext_polyval_libpolyval_a_SOURCES = \ + src/ext/polyval/polyval.c + +POLYVAL_HDRS = \ + src/ext/polyval/polyval.h \ + src/ext/polyval/pclmul.c \ + src/ext/polyval/ctmul64.c \ + src/ext/polyval/ctmul.c + +LIBPOLYVAL = src/ext/polyval/libpolyval.a # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_buf_a_SOURCES = \ @@ -6195,8 +6253,8 @@ # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_ctime_a_SOURCES = \ - $(mulodi4_source) \ - src/ext/csiphash.c \ + $(mulodi4_source) \ + src/ext/csiphash.c \ src/lib/ctime/di_ops.c src_lib_libtor_ctime_testing_a_SOURCES = \ @@ -6222,10 +6280,10 @@ # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_confmgt_a_SOURCES = \ - src/lib/confmgt/confmgt.c \ - src/lib/confmgt/structvar.c \ - src/lib/confmgt/type_defs.c \ - src/lib/confmgt/typedvar.c \ + src/lib/confmgt/confmgt.c \ + src/lib/confmgt/structvar.c \ + src/lib/confmgt/type_defs.c \ + src/lib/confmgt/typedvar.c \ src/lib/confmgt/unitparse.c src_lib_libtor_confmgt_testing_a_SOURCES = \ @@ -6419,7 +6477,7 @@ # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_math_a_SOURCES = \ - src/lib/math/fp.c \ + src/lib/math/fp.c \ src/lib/math/laplace.c \ src/lib/math/prob_distr.c @@ -6452,8 +6510,8 @@ # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_metrics_a_SOURCES = \ src/lib/metrics/metrics_store.c \ - src/lib/metrics/metrics_store_entry.c \ - src/lib/metrics/metrics_common.c \ + src/lib/metrics/metrics_store_entry.c \ + src/lib/metrics/metrics_common.c \ src/lib/metrics/prometheus.c src_lib_libtor_metrics_testing_a_SOURCES = \ @@ -6465,7 +6523,7 @@ # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_net_a_SOURCES = \ src/lib/net/address.c \ - src/lib/net/alertsock.c \ + src/lib/net/alertsock.c \ src/lib/net/buffers_net.c \ src/lib/net/gethostname.c \ src/lib/net/inaddr.c \ @@ -6549,7 +6607,7 @@ # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_smartlist_core_a_SOURCES = \ - src/lib/smartlist_core/smartlist_core.c \ + src/lib/smartlist_core/smartlist_core.c \ src/lib/smartlist_core/smartlist_split.c src_lib_libtor_smartlist_core_testing_a_SOURCES = \ @@ -6658,45 +6716,48 @@ src/trunnel/congestion_control.trunnel \ src/trunnel/socks5.trunnel \ src/trunnel/circpad_negotiation.trunnel \ - src/trunnel/conflux.trunnel + src/trunnel/conflux.trunnel \ + src/trunnel/subproto_request.trunnel TRUNNELSOURCES = \ src/ext/trunnel/trunnel.c \ src/trunnel/ed25519_cert.c \ src/trunnel/extension.c \ src/trunnel/link_handshake.c \ - src/trunnel/pwbox.c \ - src/trunnel/hs/cell_establish_intro.c \ + src/trunnel/pwbox.c \ + src/trunnel/hs/cell_establish_intro.c \ src/trunnel/hs/cell_introduce1.c \ src/trunnel/hs/cell_rendezvous.c \ src/trunnel/channelpadding_negotiation.c \ - src/trunnel/sendme_cell.c \ - src/trunnel/flow_control_cells.c \ - src/trunnel/congestion_control.c \ + src/trunnel/sendme_cell.c \ + src/trunnel/flow_control_cells.c \ + src/trunnel/congestion_control.c \ src/trunnel/socks5.c \ src/trunnel/netinfo.c \ src/trunnel/circpad_negotiation.c \ - src/trunnel/conflux.c + src/trunnel/conflux.c \ + src/trunnel/subproto_request.c TRUNNELHEADERS = \ - src/ext/trunnel/trunnel.h \ - src/ext/trunnel/trunnel-impl.h \ - src/trunnel/trunnel-local.h \ - src/trunnel/ed25519_cert.h \ + src/ext/trunnel/trunnel.h \ + src/ext/trunnel/trunnel-impl.h \ + src/trunnel/trunnel-local.h \ + src/trunnel/ed25519_cert.h \ src/trunnel/extension.h \ - src/trunnel/link_handshake.h \ - src/trunnel/pwbox.h \ - src/trunnel/hs/cell_establish_intro.h \ + src/trunnel/link_handshake.h \ + src/trunnel/pwbox.h \ + src/trunnel/hs/cell_establish_intro.h \ src/trunnel/hs/cell_introduce1.h \ src/trunnel/hs/cell_rendezvous.h \ src/trunnel/channelpadding_negotiation.h \ - src/trunnel/sendme_cell.h \ - src/trunnel/flow_control_cells.h \ - src/trunnel/congestion_control.h \ - src/trunnel/socks5.h \ + src/trunnel/sendme_cell.h \ + src/trunnel/flow_control_cells.h \ + src/trunnel/congestion_control.h \ + src/trunnel/socks5.h \ src/trunnel/netinfo.h \ src/trunnel/circpad_negotiation.h \ - src/trunnel/conflux.h + src/trunnel/conflux.h \ + src/trunnel/subproto_request.h src_trunnel_libor_trunnel_a_SOURCES = $(TRUNNELSOURCES) src_trunnel_libor_trunnel_a_CPPFLAGS = \ @@ -6751,7 +6812,9 @@ LIBTOR_APP_A_SOURCES = src/core/crypto/hs_ntor.c \ src/core/crypto/onion_crypto.c src/core/crypto/onion_fast.c \ src/core/crypto/onion_ntor.c src/core/crypto/onion_ntor_v3.c \ - src/core/crypto/onion_tap.c src/core/crypto/relay_crypto.c \ + src/core/crypto/relay_crypto.c \ + src/core/crypto/relay_crypto_cgo.c \ + src/core/crypto/relay_crypto_tor1.c \ src/core/mainloop/connection.c src/core/mainloop/cpuworker.c \ src/core/mainloop/mainloop.c \ src/core/mainloop/mainloop_pubsub.c \ @@ -6771,9 +6834,10 @@ src/core/or/or_periodic.c src/core/or/or_sys.c \ src/core/or/orconn_event.c src/core/or/policies.c \ src/core/or/protover.c src/core/or/reasons.c \ - src/core/or/relay.c src/core/or/scheduler.c \ - src/core/or/scheduler_kist.c src/core/or/scheduler_vanilla.c \ - src/core/or/sendme.c src/core/or/congestion_control_common.c \ + src/core/or/relay.c src/core/or/relay_msg.c \ + src/core/or/scheduler.c src/core/or/scheduler_kist.c \ + src/core/or/scheduler_vanilla.c src/core/or/sendme.c \ + src/core/or/congestion_control_common.c \ src/core/or/congestion_control_vegas.c \ src/core/or/congestion_control_flow.c src/core/or/conflux.c \ src/core/or/conflux_cell.c src/core/or/conflux_params.c \ @@ -6902,7 +6966,7 @@ MODULE_RELAY_SOURCES = \ src/feature/relay/circuitbuild_relay.c \ src/feature/relay/dns.c \ - src/feature/relay/ext_orport.c \ + src/feature/relay/ext_orport.c \ src/feature/relay/routermode.c \ src/feature/relay/relay_config.c \ src/feature/relay/relay_handshake.c \ @@ -7007,8 +7071,8 @@ TEST_CHUTNEY_FLAVORS_IPV6_MIXED = mixed+hs-v3-ipv6 src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ -DLOCALSTATEDIR="\"$(localstatedir)\"" \ - -DBINDIR="\"$(bindir)\"" \ - -DTOR_UNIT_TESTS \ + -DBINDIR="\"$(bindir)\"" \ + -DTOR_UNIT_TESTS \ $(AM_CPPFLAGS) @@ -7075,7 +7139,7 @@ @TOR_LDFLAGS_libevent@ src_test_bench_LDADD = \ - libtor.a \ + libtor.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ @CURVE25519_LIBS@ \ @@ -7120,7 +7184,7 @@ libtor.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ \ - @CURVE25519_LIBS@ @TOR_TRACE_LIBS@ + @CURVE25519_LIBS@ @TOR_TRACE_LIBS@ src_test_test_hs_ntor_cl_AM_CPPFLAGS = \ $(AM_CPPFLAGS) @@ -7130,7 +7194,7 @@ @UNITTESTS_ENABLED_TRUE@ $(TOR_UTIL_TESTING_LIBS) \ @UNITTESTS_ENABLED_TRUE@ @TOR_LIB_MATH@ \ @UNITTESTS_ENABLED_TRUE@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ -@UNITTESTS_ENABLED_TRUE@ @TOR_TRACE_LIBS@ +@UNITTESTS_ENABLED_TRUE@ @TOR_TRACE_LIBS@ @UNITTESTS_ENABLED_TRUE@src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) @UNITTESTS_ENABLED_TRUE@src_test_test_bt_cl_CPPFLAGS = $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) @@ -7139,7 +7203,7 @@ src_tools_tor_resolve_LDADD = \ src/trunnel/libor-trunnel.a \ $(TOR_UTIL_LIBS) \ - $(TOR_CRYPTO_LIBS) $(TOR_LIBS_CRYPTLIB)\ + $(TOR_CRYPTO_LIBS) $(TOR_LIBS_CRYPTLIB)\ @TOR_LIB_MATH@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_USERENV@ @COVERAGE_ENABLED_TRUE@src_tools_tor_cov_resolve_SOURCES = src/tools/tor-resolve.c @@ -7164,8 +7228,8 @@ src_tools_tor_print_ed_signing_cert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ src_tools_tor_print_ed_signing_cert_LDADD = \ src/trunnel/libor-trunnel.a \ - $(TOR_CRYPTO_LIBS) \ - $(TOR_UTIL_LIBS) \ + $(TOR_CRYPTO_LIBS) \ + $(TOR_UTIL_LIBS) \ @TOR_LIB_MATH@ $(TOR_LIBS_CRYPTLIB) \ @TOR_LIB_WS32@ @TOR_LIB_USERENV@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @@ -7180,8 +7244,8 @@ @COVERAGE_ENABLED_TRUE@@USE_NSS_FALSE@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ @BUILD_LIBTORRUNNER_TRUE@src_tools_libtorrunner_a_SOURCES = \ -@BUILD_LIBTORRUNNER_TRUE@ src/tools/tor_runner.c \ -@BUILD_LIBTORRUNNER_TRUE@ src/feature/api/tor_api.c +@BUILD_LIBTORRUNNER_TRUE@ src/tools/tor_runner.c \ +@BUILD_LIBTORRUNNER_TRUE@ src/feature/api/tor_api.c confdir = $(sysconfdir)/tor tordatadir = $(datadir)/tor @@ -7777,10 +7841,13 @@ src/core/crypto/libtor_app_testing_a-onion_ntor_v3.$(OBJEXT): \ src/core/crypto/$(am__dirstamp) \ src/core/crypto/$(DEPDIR)/$(am__dirstamp) -src/core/crypto/libtor_app_testing_a-onion_tap.$(OBJEXT): \ +src/core/crypto/libtor_app_testing_a-relay_crypto.$(OBJEXT): \ src/core/crypto/$(am__dirstamp) \ src/core/crypto/$(DEPDIR)/$(am__dirstamp) -src/core/crypto/libtor_app_testing_a-relay_crypto.$(OBJEXT): \ +src/core/crypto/libtor_app_testing_a-relay_crypto_cgo.$(OBJEXT): \ + src/core/crypto/$(am__dirstamp) \ + src/core/crypto/$(DEPDIR)/$(am__dirstamp) +src/core/crypto/libtor_app_testing_a-relay_crypto_tor1.$(OBJEXT): \ src/core/crypto/$(am__dirstamp) \ src/core/crypto/$(DEPDIR)/$(am__dirstamp) src/core/mainloop/$(am__dirstamp): @@ -7903,6 +7970,9 @@ src/core/or/libtor_app_testing_a-relay.$(OBJEXT): \ src/core/or/$(am__dirstamp) \ src/core/or/$(DEPDIR)/$(am__dirstamp) +src/core/or/libtor_app_testing_a-relay_msg.$(OBJEXT): \ + src/core/or/$(am__dirstamp) \ + src/core/or/$(DEPDIR)/$(am__dirstamp) src/core/or/libtor_app_testing_a-scheduler.$(OBJEXT): \ src/core/or/$(am__dirstamp) \ src/core/or/$(DEPDIR)/$(am__dirstamp) @@ -8505,11 +8575,15 @@ src/core/crypto/onion_ntor_v3.$(OBJEXT): \ src/core/crypto/$(am__dirstamp) \ src/core/crypto/$(DEPDIR)/$(am__dirstamp) -src/core/crypto/onion_tap.$(OBJEXT): src/core/crypto/$(am__dirstamp) \ - src/core/crypto/$(DEPDIR)/$(am__dirstamp) src/core/crypto/relay_crypto.$(OBJEXT): \ src/core/crypto/$(am__dirstamp) \ src/core/crypto/$(DEPDIR)/$(am__dirstamp) +src/core/crypto/relay_crypto_cgo.$(OBJEXT): \ + src/core/crypto/$(am__dirstamp) \ + src/core/crypto/$(DEPDIR)/$(am__dirstamp) +src/core/crypto/relay_crypto_tor1.$(OBJEXT): \ + src/core/crypto/$(am__dirstamp) \ + src/core/crypto/$(DEPDIR)/$(am__dirstamp) src/core/mainloop/connection.$(OBJEXT): \ src/core/mainloop/$(am__dirstamp) \ src/core/mainloop/$(DEPDIR)/$(am__dirstamp) @@ -8590,6 +8664,8 @@ src/core/or/$(DEPDIR)/$(am__dirstamp) src/core/or/relay.$(OBJEXT): src/core/or/$(am__dirstamp) \ src/core/or/$(DEPDIR)/$(am__dirstamp) +src/core/or/relay_msg.$(OBJEXT): src/core/or/$(am__dirstamp) \ + src/core/or/$(DEPDIR)/$(am__dirstamp) src/core/or/scheduler.$(OBJEXT): src/core/or/$(am__dirstamp) \ src/core/or/$(DEPDIR)/$(am__dirstamp) src/core/or/scheduler_kist.$(OBJEXT): src/core/or/$(am__dirstamp) \ @@ -9248,6 +9324,20 @@ $(AM_V_at)-rm -f src/ext/keccak-tiny/libkeccak-tiny.a $(AM_V_AR)$(src_ext_keccak_tiny_libkeccak_tiny_a_AR) src/ext/keccak-tiny/libkeccak-tiny.a $(src_ext_keccak_tiny_libkeccak_tiny_a_OBJECTS) $(src_ext_keccak_tiny_libkeccak_tiny_a_LIBADD) $(AM_V_at)$(RANLIB) src/ext/keccak-tiny/libkeccak-tiny.a +src/ext/polyval/$(am__dirstamp): + @$(MKDIR_P) src/ext/polyval + @: > src/ext/polyval/$(am__dirstamp) +src/ext/polyval/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/ext/polyval/$(DEPDIR) + @: > src/ext/polyval/$(DEPDIR)/$(am__dirstamp) +src/ext/polyval/libpolyval_a-polyval.$(OBJEXT): \ + src/ext/polyval/$(am__dirstamp) \ + src/ext/polyval/$(DEPDIR)/$(am__dirstamp) + +src/ext/polyval/libpolyval.a: $(src_ext_polyval_libpolyval_a_OBJECTS) $(src_ext_polyval_libpolyval_a_DEPENDENCIES) $(EXTRA_src_ext_polyval_libpolyval_a_DEPENDENCIES) src/ext/polyval/$(am__dirstamp) + $(AM_V_at)-rm -f src/ext/polyval/libpolyval.a + $(AM_V_AR)$(src_ext_polyval_libpolyval_a_AR) src/ext/polyval/libpolyval.a $(src_ext_polyval_libpolyval_a_OBJECTS) $(src_ext_polyval_libpolyval_a_LIBADD) + $(AM_V_at)$(RANLIB) src/ext/polyval/libpolyval.a src/ext/curve25519_donna/$(am__dirstamp): @$(MKDIR_P) src/ext/curve25519_donna @: > src/ext/curve25519_donna/$(am__dirstamp) @@ -10989,6 +11079,9 @@ src/trunnel/libor_trunnel_testing_a-conflux.$(OBJEXT): \ src/trunnel/$(am__dirstamp) \ src/trunnel/$(DEPDIR)/$(am__dirstamp) +src/trunnel/libor_trunnel_testing_a-subproto_request.$(OBJEXT): \ + src/trunnel/$(am__dirstamp) \ + src/trunnel/$(DEPDIR)/$(am__dirstamp) src/trunnel/libor-trunnel-testing.a: $(src_trunnel_libor_trunnel_testing_a_OBJECTS) $(src_trunnel_libor_trunnel_testing_a_DEPENDENCIES) $(EXTRA_src_trunnel_libor_trunnel_testing_a_DEPENDENCIES) src/trunnel/$(am__dirstamp) $(AM_V_at)-rm -f src/trunnel/libor-trunnel-testing.a @@ -11042,6 +11135,9 @@ src/trunnel/libor_trunnel_a-conflux.$(OBJEXT): \ src/trunnel/$(am__dirstamp) \ src/trunnel/$(DEPDIR)/$(am__dirstamp) +src/trunnel/libor_trunnel_a-subproto_request.$(OBJEXT): \ + src/trunnel/$(am__dirstamp) \ + src/trunnel/$(DEPDIR)/$(am__dirstamp) src/trunnel/libor-trunnel.a: $(src_trunnel_libor_trunnel_a_OBJECTS) $(src_trunnel_libor_trunnel_a_DEPENDENCIES) $(EXTRA_src_trunnel_libor_trunnel_a_DEPENDENCIES) src/trunnel/$(am__dirstamp) $(AM_V_at)-rm -f src/trunnel/libor-trunnel.a @@ -11484,6 +11580,8 @@ src/test/$(DEPDIR)/$(am__dirstamp) src/test/test-test_crypto_rng.$(OBJEXT): src/test/$(am__dirstamp) \ src/test/$(DEPDIR)/$(am__dirstamp) +src/test/test-test_crypto_cgo.$(OBJEXT): src/test/$(am__dirstamp) \ + src/test/$(DEPDIR)/$(am__dirstamp) src/test/test-test_data.$(OBJEXT): src/test/$(am__dirstamp) \ src/test/$(DEPDIR)/$(am__dirstamp) src/test/test-test_dir.$(OBJEXT): src/test/$(am__dirstamp) \ @@ -11830,6 +11928,7 @@ -rm -f src/ext/equix/src/*.$(OBJEXT) -rm -f src/ext/keccak-tiny/*.$(OBJEXT) -rm -f src/ext/mulodi/*.$(OBJEXT) + -rm -f src/ext/polyval/*.$(OBJEXT) -rm -f src/ext/trunnel/*.$(OBJEXT) -rm -f src/feature/api/*.$(OBJEXT) -rm -f src/feature/client/*.$(OBJEXT) @@ -11921,14 +12020,16 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_fast.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_ntor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_ntor_v3.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_tap.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_cgo.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_tor1.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/onion_crypto.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/onion_fast.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/onion_ntor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/onion_ntor_v3.Po@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/onion_tap.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/relay_crypto.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/relay_crypto_cgo.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/core/crypto/$(DEPDIR)/relay_crypto_tor1.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/mainloop/$(DEPDIR)/connection.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/mainloop/$(DEPDIR)/cpuworker.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/mainloop/$(DEPDIR)/libtor_app_testing_a-connection.Po@am__quote@ # am--include-marker @@ -12010,6 +12111,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/libtor_app_testing_a-protover.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/libtor_app_testing_a-reasons.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/libtor_app_testing_a-relay.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/libtor_app_testing_a-relay_msg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler_kist.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler_vanilla.Po@am__quote@ # am--include-marker @@ -12027,6 +12129,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/protover.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/reasons.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/relay.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/relay_msg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/scheduler.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/scheduler_kist.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/core/or/$(DEPDIR)/scheduler_vanilla.Po@am__quote@ # am--include-marker @@ -12116,6 +12219,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/ext/keccak-tiny/$(DEPDIR)/libkeccak_tiny_a-keccak-tiny-unrolled.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ext/mulodi/$(DEPDIR)/lib_libtor_ctime_a-mulodi4.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ext/mulodi/$(DEPDIR)/lib_libtor_ctime_testing_a-mulodi4.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/ext/polyval/$(DEPDIR)/libpolyval_a-polyval.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ext/trunnel/$(DEPDIR)/trunnel_libor_trunnel_a-trunnel.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/ext/trunnel/$(DEPDIR)/trunnel_libor_trunnel_testing_a-trunnel.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/feature/api/$(DEPDIR)/core_libtor_app_testing_a-tor_api.Po@am__quote@ # am--include-marker @@ -12725,6 +12829,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/test/$(DEPDIR)/test-test_controller.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/test/$(DEPDIR)/test-test_controller_events.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/test/$(DEPDIR)/test-test_crypto.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/test/$(DEPDIR)/test-test_crypto_cgo.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/test/$(DEPDIR)/test-test_crypto_ope.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/test/$(DEPDIR)/test-test_crypto_openssl.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/test/$(DEPDIR)/test-test_crypto_rng.Po@am__quote@ # am--include-marker @@ -12948,6 +13053,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/$(DEPDIR)/libor_trunnel_a-pwbox.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/$(DEPDIR)/libor_trunnel_a-sendme_cell.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/$(DEPDIR)/libor_trunnel_a-socks5.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/$(DEPDIR)/libor_trunnel_a-subproto_request.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-channelpadding_negotiation.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-circpad_negotiation.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-conflux.Po@am__quote@ # am--include-marker @@ -12960,6 +13066,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-pwbox.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-sendme_cell.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-socks5.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-subproto_request.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/hs/$(DEPDIR)/libor_trunnel_a-cell_establish_intro.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/hs/$(DEPDIR)/libor_trunnel_a-cell_introduce1.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@src/trunnel/hs/$(DEPDIR)/libor_trunnel_a-cell_rendezvous.Po@am__quote@ # am--include-marker @@ -13059,20 +13166,6 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -c -o src/core/crypto/libtor_app_testing_a-onion_ntor_v3.obj `if test -f 'src/core/crypto/onion_ntor_v3.c'; then $(CYGPATH_W) 'src/core/crypto/onion_ntor_v3.c'; else $(CYGPATH_W) '$(srcdir)/src/core/crypto/onion_ntor_v3.c'; fi` -src/core/crypto/libtor_app_testing_a-onion_tap.o: src/core/crypto/onion_tap.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -MT src/core/crypto/libtor_app_testing_a-onion_tap.o -MD -MP -MF src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_tap.Tpo -c -o src/core/crypto/libtor_app_testing_a-onion_tap.o `test -f 'src/core/crypto/onion_tap.c' || echo '$(srcdir)/'`src/core/crypto/onion_tap.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_tap.Tpo src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_tap.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/core/crypto/onion_tap.c' object='src/core/crypto/libtor_app_testing_a-onion_tap.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -c -o src/core/crypto/libtor_app_testing_a-onion_tap.o `test -f 'src/core/crypto/onion_tap.c' || echo '$(srcdir)/'`src/core/crypto/onion_tap.c - -src/core/crypto/libtor_app_testing_a-onion_tap.obj: src/core/crypto/onion_tap.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -MT src/core/crypto/libtor_app_testing_a-onion_tap.obj -MD -MP -MF src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_tap.Tpo -c -o src/core/crypto/libtor_app_testing_a-onion_tap.obj `if test -f 'src/core/crypto/onion_tap.c'; then $(CYGPATH_W) 'src/core/crypto/onion_tap.c'; else $(CYGPATH_W) '$(srcdir)/src/core/crypto/onion_tap.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_tap.Tpo src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_tap.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/core/crypto/onion_tap.c' object='src/core/crypto/libtor_app_testing_a-onion_tap.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -c -o src/core/crypto/libtor_app_testing_a-onion_tap.obj `if test -f 'src/core/crypto/onion_tap.c'; then $(CYGPATH_W) 'src/core/crypto/onion_tap.c'; else $(CYGPATH_W) '$(srcdir)/src/core/crypto/onion_tap.c'; fi` - src/core/crypto/libtor_app_testing_a-relay_crypto.o: src/core/crypto/relay_crypto.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -MT src/core/crypto/libtor_app_testing_a-relay_crypto.o -MD -MP -MF src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto.Tpo -c -o src/core/crypto/libtor_app_testing_a-relay_crypto.o `test -f 'src/core/crypto/relay_crypto.c' || echo '$(srcdir)/'`src/core/crypto/relay_crypto.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto.Tpo src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto.Po @@ -13087,6 +13180,34 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -c -o src/core/crypto/libtor_app_testing_a-relay_crypto.obj `if test -f 'src/core/crypto/relay_crypto.c'; then $(CYGPATH_W) 'src/core/crypto/relay_crypto.c'; else $(CYGPATH_W) '$(srcdir)/src/core/crypto/relay_crypto.c'; fi` +src/core/crypto/libtor_app_testing_a-relay_crypto_cgo.o: src/core/crypto/relay_crypto_cgo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -MT src/core/crypto/libtor_app_testing_a-relay_crypto_cgo.o -MD -MP -MF src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_cgo.Tpo -c -o src/core/crypto/libtor_app_testing_a-relay_crypto_cgo.o `test -f 'src/core/crypto/relay_crypto_cgo.c' || echo '$(srcdir)/'`src/core/crypto/relay_crypto_cgo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_cgo.Tpo src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_cgo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/core/crypto/relay_crypto_cgo.c' object='src/core/crypto/libtor_app_testing_a-relay_crypto_cgo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -c -o src/core/crypto/libtor_app_testing_a-relay_crypto_cgo.o `test -f 'src/core/crypto/relay_crypto_cgo.c' || echo '$(srcdir)/'`src/core/crypto/relay_crypto_cgo.c + +src/core/crypto/libtor_app_testing_a-relay_crypto_cgo.obj: src/core/crypto/relay_crypto_cgo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -MT src/core/crypto/libtor_app_testing_a-relay_crypto_cgo.obj -MD -MP -MF src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_cgo.Tpo -c -o src/core/crypto/libtor_app_testing_a-relay_crypto_cgo.obj `if test -f 'src/core/crypto/relay_crypto_cgo.c'; then $(CYGPATH_W) 'src/core/crypto/relay_crypto_cgo.c'; else $(CYGPATH_W) '$(srcdir)/src/core/crypto/relay_crypto_cgo.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_cgo.Tpo src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_cgo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/core/crypto/relay_crypto_cgo.c' object='src/core/crypto/libtor_app_testing_a-relay_crypto_cgo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -c -o src/core/crypto/libtor_app_testing_a-relay_crypto_cgo.obj `if test -f 'src/core/crypto/relay_crypto_cgo.c'; then $(CYGPATH_W) 'src/core/crypto/relay_crypto_cgo.c'; else $(CYGPATH_W) '$(srcdir)/src/core/crypto/relay_crypto_cgo.c'; fi` + +src/core/crypto/libtor_app_testing_a-relay_crypto_tor1.o: src/core/crypto/relay_crypto_tor1.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -MT src/core/crypto/libtor_app_testing_a-relay_crypto_tor1.o -MD -MP -MF src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_tor1.Tpo -c -o src/core/crypto/libtor_app_testing_a-relay_crypto_tor1.o `test -f 'src/core/crypto/relay_crypto_tor1.c' || echo '$(srcdir)/'`src/core/crypto/relay_crypto_tor1.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_tor1.Tpo src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_tor1.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/core/crypto/relay_crypto_tor1.c' object='src/core/crypto/libtor_app_testing_a-relay_crypto_tor1.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -c -o src/core/crypto/libtor_app_testing_a-relay_crypto_tor1.o `test -f 'src/core/crypto/relay_crypto_tor1.c' || echo '$(srcdir)/'`src/core/crypto/relay_crypto_tor1.c + +src/core/crypto/libtor_app_testing_a-relay_crypto_tor1.obj: src/core/crypto/relay_crypto_tor1.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -MT src/core/crypto/libtor_app_testing_a-relay_crypto_tor1.obj -MD -MP -MF src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_tor1.Tpo -c -o src/core/crypto/libtor_app_testing_a-relay_crypto_tor1.obj `if test -f 'src/core/crypto/relay_crypto_tor1.c'; then $(CYGPATH_W) 'src/core/crypto/relay_crypto_tor1.c'; else $(CYGPATH_W) '$(srcdir)/src/core/crypto/relay_crypto_tor1.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_tor1.Tpo src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_tor1.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/core/crypto/relay_crypto_tor1.c' object='src/core/crypto/libtor_app_testing_a-relay_crypto_tor1.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -c -o src/core/crypto/libtor_app_testing_a-relay_crypto_tor1.obj `if test -f 'src/core/crypto/relay_crypto_tor1.c'; then $(CYGPATH_W) 'src/core/crypto/relay_crypto_tor1.c'; else $(CYGPATH_W) '$(srcdir)/src/core/crypto/relay_crypto_tor1.c'; fi` + src/core/mainloop/libtor_app_testing_a-connection.o: src/core/mainloop/connection.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -MT src/core/mainloop/libtor_app_testing_a-connection.o -MD -MP -MF src/core/mainloop/$(DEPDIR)/libtor_app_testing_a-connection.Tpo -c -o src/core/mainloop/libtor_app_testing_a-connection.o `test -f 'src/core/mainloop/connection.c' || echo '$(srcdir)/'`src/core/mainloop/connection.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/core/mainloop/$(DEPDIR)/libtor_app_testing_a-connection.Tpo src/core/mainloop/$(DEPDIR)/libtor_app_testing_a-connection.Po @@ -13591,6 +13712,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -c -o src/core/or/libtor_app_testing_a-relay.obj `if test -f 'src/core/or/relay.c'; then $(CYGPATH_W) 'src/core/or/relay.c'; else $(CYGPATH_W) '$(srcdir)/src/core/or/relay.c'; fi` +src/core/or/libtor_app_testing_a-relay_msg.o: src/core/or/relay_msg.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -MT src/core/or/libtor_app_testing_a-relay_msg.o -MD -MP -MF src/core/or/$(DEPDIR)/libtor_app_testing_a-relay_msg.Tpo -c -o src/core/or/libtor_app_testing_a-relay_msg.o `test -f 'src/core/or/relay_msg.c' || echo '$(srcdir)/'`src/core/or/relay_msg.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/core/or/$(DEPDIR)/libtor_app_testing_a-relay_msg.Tpo src/core/or/$(DEPDIR)/libtor_app_testing_a-relay_msg.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/core/or/relay_msg.c' object='src/core/or/libtor_app_testing_a-relay_msg.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -c -o src/core/or/libtor_app_testing_a-relay_msg.o `test -f 'src/core/or/relay_msg.c' || echo '$(srcdir)/'`src/core/or/relay_msg.c + +src/core/or/libtor_app_testing_a-relay_msg.obj: src/core/or/relay_msg.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -MT src/core/or/libtor_app_testing_a-relay_msg.obj -MD -MP -MF src/core/or/$(DEPDIR)/libtor_app_testing_a-relay_msg.Tpo -c -o src/core/or/libtor_app_testing_a-relay_msg.obj `if test -f 'src/core/or/relay_msg.c'; then $(CYGPATH_W) 'src/core/or/relay_msg.c'; else $(CYGPATH_W) '$(srcdir)/src/core/or/relay_msg.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/core/or/$(DEPDIR)/libtor_app_testing_a-relay_msg.Tpo src/core/or/$(DEPDIR)/libtor_app_testing_a-relay_msg.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/core/or/relay_msg.c' object='src/core/or/libtor_app_testing_a-relay_msg.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -c -o src/core/or/libtor_app_testing_a-relay_msg.obj `if test -f 'src/core/or/relay_msg.c'; then $(CYGPATH_W) 'src/core/or/relay_msg.c'; else $(CYGPATH_W) '$(srcdir)/src/core/or/relay_msg.c'; fi` + src/core/or/libtor_app_testing_a-scheduler.o: src/core/or/scheduler.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_core_libtor_app_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_core_libtor_app_testing_a_CFLAGS) $(CFLAGS) -MT src/core/or/libtor_app_testing_a-scheduler.o -MD -MP -MF src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler.Tpo -c -o src/core/or/libtor_app_testing_a-scheduler.o `test -f 'src/core/or/scheduler.c' || echo '$(srcdir)/'`src/core/or/scheduler.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler.Tpo src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler.Po @@ -16545,6 +16680,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_ext_keccak_tiny_libkeccak_tiny_a_CFLAGS) $(CFLAGS) -c -o src/ext/keccak-tiny/libkeccak_tiny_a-keccak-tiny-unrolled.obj `if test -f 'src/ext/keccak-tiny/keccak-tiny-unrolled.c'; then $(CYGPATH_W) 'src/ext/keccak-tiny/keccak-tiny-unrolled.c'; else $(CYGPATH_W) '$(srcdir)/src/ext/keccak-tiny/keccak-tiny-unrolled.c'; fi` +src/ext/polyval/libpolyval_a-polyval.o: src/ext/polyval/polyval.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_ext_polyval_libpolyval_a_CFLAGS) $(CFLAGS) -MT src/ext/polyval/libpolyval_a-polyval.o -MD -MP -MF src/ext/polyval/$(DEPDIR)/libpolyval_a-polyval.Tpo -c -o src/ext/polyval/libpolyval_a-polyval.o `test -f 'src/ext/polyval/polyval.c' || echo '$(srcdir)/'`src/ext/polyval/polyval.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ext/polyval/$(DEPDIR)/libpolyval_a-polyval.Tpo src/ext/polyval/$(DEPDIR)/libpolyval_a-polyval.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ext/polyval/polyval.c' object='src/ext/polyval/libpolyval_a-polyval.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_ext_polyval_libpolyval_a_CFLAGS) $(CFLAGS) -c -o src/ext/polyval/libpolyval_a-polyval.o `test -f 'src/ext/polyval/polyval.c' || echo '$(srcdir)/'`src/ext/polyval/polyval.c + +src/ext/polyval/libpolyval_a-polyval.obj: src/ext/polyval/polyval.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_ext_polyval_libpolyval_a_CFLAGS) $(CFLAGS) -MT src/ext/polyval/libpolyval_a-polyval.obj -MD -MP -MF src/ext/polyval/$(DEPDIR)/libpolyval_a-polyval.Tpo -c -o src/ext/polyval/libpolyval_a-polyval.obj `if test -f 'src/ext/polyval/polyval.c'; then $(CYGPATH_W) 'src/ext/polyval/polyval.c'; else $(CYGPATH_W) '$(srcdir)/src/ext/polyval/polyval.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ext/polyval/$(DEPDIR)/libpolyval_a-polyval.Tpo src/ext/polyval/$(DEPDIR)/libpolyval_a-polyval.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/ext/polyval/polyval.c' object='src/ext/polyval/libpolyval_a-polyval.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_ext_polyval_libpolyval_a_CFLAGS) $(CFLAGS) -c -o src/ext/polyval/libpolyval_a-polyval.obj `if test -f 'src/ext/polyval/polyval.c'; then $(CYGPATH_W) 'src/ext/polyval/polyval.c'; else $(CYGPATH_W) '$(srcdir)/src/ext/polyval/polyval.c'; fi` + src/ext/curve25519_donna/lib_libcurve25519_donna_a-curve25519-donna-c64.o: src/ext/curve25519_donna/curve25519-donna-c64.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(src_lib_libcurve25519_donna_a_CFLAGS) $(CFLAGS) -MT src/ext/curve25519_donna/lib_libcurve25519_donna_a-curve25519-donna-c64.o -MD -MP -MF src/ext/curve25519_donna/$(DEPDIR)/lib_libcurve25519_donna_a-curve25519-donna-c64.Tpo -c -o src/ext/curve25519_donna/lib_libcurve25519_donna_a-curve25519-donna-c64.o `test -f 'src/ext/curve25519_donna/curve25519-donna-c64.c' || echo '$(srcdir)/'`src/ext/curve25519_donna/curve25519-donna-c64.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ext/curve25519_donna/$(DEPDIR)/lib_libcurve25519_donna_a-curve25519-donna-c64.Tpo src/ext/curve25519_donna/$(DEPDIR)/lib_libcurve25519_donna_a-curve25519-donna-c64.Po @@ -20031,6 +20180,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_trunnel_libor_trunnel_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_trunnel_libor_trunnel_testing_a_CFLAGS) $(CFLAGS) -c -o src/trunnel/libor_trunnel_testing_a-conflux.obj `if test -f 'src/trunnel/conflux.c'; then $(CYGPATH_W) 'src/trunnel/conflux.c'; else $(CYGPATH_W) '$(srcdir)/src/trunnel/conflux.c'; fi` +src/trunnel/libor_trunnel_testing_a-subproto_request.o: src/trunnel/subproto_request.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_trunnel_libor_trunnel_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_trunnel_libor_trunnel_testing_a_CFLAGS) $(CFLAGS) -MT src/trunnel/libor_trunnel_testing_a-subproto_request.o -MD -MP -MF src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-subproto_request.Tpo -c -o src/trunnel/libor_trunnel_testing_a-subproto_request.o `test -f 'src/trunnel/subproto_request.c' || echo '$(srcdir)/'`src/trunnel/subproto_request.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-subproto_request.Tpo src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-subproto_request.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/trunnel/subproto_request.c' object='src/trunnel/libor_trunnel_testing_a-subproto_request.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_trunnel_libor_trunnel_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_trunnel_libor_trunnel_testing_a_CFLAGS) $(CFLAGS) -c -o src/trunnel/libor_trunnel_testing_a-subproto_request.o `test -f 'src/trunnel/subproto_request.c' || echo '$(srcdir)/'`src/trunnel/subproto_request.c + +src/trunnel/libor_trunnel_testing_a-subproto_request.obj: src/trunnel/subproto_request.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_trunnel_libor_trunnel_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_trunnel_libor_trunnel_testing_a_CFLAGS) $(CFLAGS) -MT src/trunnel/libor_trunnel_testing_a-subproto_request.obj -MD -MP -MF src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-subproto_request.Tpo -c -o src/trunnel/libor_trunnel_testing_a-subproto_request.obj `if test -f 'src/trunnel/subproto_request.c'; then $(CYGPATH_W) 'src/trunnel/subproto_request.c'; else $(CYGPATH_W) '$(srcdir)/src/trunnel/subproto_request.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-subproto_request.Tpo src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-subproto_request.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/trunnel/subproto_request.c' object='src/trunnel/libor_trunnel_testing_a-subproto_request.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_trunnel_libor_trunnel_testing_a_CPPFLAGS) $(CPPFLAGS) $(src_trunnel_libor_trunnel_testing_a_CFLAGS) $(CFLAGS) -c -o src/trunnel/libor_trunnel_testing_a-subproto_request.obj `if test -f 'src/trunnel/subproto_request.c'; then $(CYGPATH_W) 'src/trunnel/subproto_request.c'; else $(CYGPATH_W) '$(srcdir)/src/trunnel/subproto_request.c'; fi` + src/ext/trunnel/trunnel_libor_trunnel_a-trunnel.o: src/ext/trunnel/trunnel.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_trunnel_libor_trunnel_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/ext/trunnel/trunnel_libor_trunnel_a-trunnel.o -MD -MP -MF src/ext/trunnel/$(DEPDIR)/trunnel_libor_trunnel_a-trunnel.Tpo -c -o src/ext/trunnel/trunnel_libor_trunnel_a-trunnel.o `test -f 'src/ext/trunnel/trunnel.c' || echo '$(srcdir)/'`src/ext/trunnel/trunnel.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/ext/trunnel/$(DEPDIR)/trunnel_libor_trunnel_a-trunnel.Tpo src/ext/trunnel/$(DEPDIR)/trunnel_libor_trunnel_a-trunnel.Po @@ -20255,6 +20418,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_trunnel_libor_trunnel_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/trunnel/libor_trunnel_a-conflux.obj `if test -f 'src/trunnel/conflux.c'; then $(CYGPATH_W) 'src/trunnel/conflux.c'; else $(CYGPATH_W) '$(srcdir)/src/trunnel/conflux.c'; fi` +src/trunnel/libor_trunnel_a-subproto_request.o: src/trunnel/subproto_request.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_trunnel_libor_trunnel_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/trunnel/libor_trunnel_a-subproto_request.o -MD -MP -MF src/trunnel/$(DEPDIR)/libor_trunnel_a-subproto_request.Tpo -c -o src/trunnel/libor_trunnel_a-subproto_request.o `test -f 'src/trunnel/subproto_request.c' || echo '$(srcdir)/'`src/trunnel/subproto_request.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/trunnel/$(DEPDIR)/libor_trunnel_a-subproto_request.Tpo src/trunnel/$(DEPDIR)/libor_trunnel_a-subproto_request.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/trunnel/subproto_request.c' object='src/trunnel/libor_trunnel_a-subproto_request.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_trunnel_libor_trunnel_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/trunnel/libor_trunnel_a-subproto_request.o `test -f 'src/trunnel/subproto_request.c' || echo '$(srcdir)/'`src/trunnel/subproto_request.c + +src/trunnel/libor_trunnel_a-subproto_request.obj: src/trunnel/subproto_request.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_trunnel_libor_trunnel_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT src/trunnel/libor_trunnel_a-subproto_request.obj -MD -MP -MF src/trunnel/$(DEPDIR)/libor_trunnel_a-subproto_request.Tpo -c -o src/trunnel/libor_trunnel_a-subproto_request.obj `if test -f 'src/trunnel/subproto_request.c'; then $(CYGPATH_W) 'src/trunnel/subproto_request.c'; else $(CYGPATH_W) '$(srcdir)/src/trunnel/subproto_request.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/trunnel/$(DEPDIR)/libor_trunnel_a-subproto_request.Tpo src/trunnel/$(DEPDIR)/libor_trunnel_a-subproto_request.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/trunnel/subproto_request.c' object='src/trunnel/libor_trunnel_a-subproto_request.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_trunnel_libor_trunnel_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o src/trunnel/libor_trunnel_a-subproto_request.obj `if test -f 'src/trunnel/subproto_request.c'; then $(CYGPATH_W) 'src/trunnel/subproto_request.c'; else $(CYGPATH_W) '$(srcdir)/src/trunnel/subproto_request.c'; fi` + src/app/main/tor_cov-tor_main.o: src/app/main/tor_main.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_app_tor_cov_CPPFLAGS) $(CPPFLAGS) $(src_app_tor_cov_CFLAGS) $(CFLAGS) -MT src/app/main/tor_cov-tor_main.o -MD -MP -MF src/app/main/$(DEPDIR)/tor_cov-tor_main.Tpo -c -o src/app/main/tor_cov-tor_main.o `test -f 'src/app/main/tor_main.c' || echo '$(srcdir)/'`src/app/main/tor_main.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/app/main/$(DEPDIR)/tor_cov-tor_main.Tpo src/app/main/$(DEPDIR)/tor_cov-tor_main.Po @@ -21795,6 +21972,20 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_test_test_CPPFLAGS) $(CPPFLAGS) $(src_test_test_CFLAGS) $(CFLAGS) -c -o src/test/test-test_crypto_rng.obj `if test -f 'src/test/test_crypto_rng.c'; then $(CYGPATH_W) 'src/test/test_crypto_rng.c'; else $(CYGPATH_W) '$(srcdir)/src/test/test_crypto_rng.c'; fi` +src/test/test-test_crypto_cgo.o: src/test/test_crypto_cgo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_test_test_CPPFLAGS) $(CPPFLAGS) $(src_test_test_CFLAGS) $(CFLAGS) -MT src/test/test-test_crypto_cgo.o -MD -MP -MF src/test/$(DEPDIR)/test-test_crypto_cgo.Tpo -c -o src/test/test-test_crypto_cgo.o `test -f 'src/test/test_crypto_cgo.c' || echo '$(srcdir)/'`src/test/test_crypto_cgo.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/test/$(DEPDIR)/test-test_crypto_cgo.Tpo src/test/$(DEPDIR)/test-test_crypto_cgo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/test/test_crypto_cgo.c' object='src/test/test-test_crypto_cgo.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_test_test_CPPFLAGS) $(CPPFLAGS) $(src_test_test_CFLAGS) $(CFLAGS) -c -o src/test/test-test_crypto_cgo.o `test -f 'src/test/test_crypto_cgo.c' || echo '$(srcdir)/'`src/test/test_crypto_cgo.c + +src/test/test-test_crypto_cgo.obj: src/test/test_crypto_cgo.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_test_test_CPPFLAGS) $(CPPFLAGS) $(src_test_test_CFLAGS) $(CFLAGS) -MT src/test/test-test_crypto_cgo.obj -MD -MP -MF src/test/$(DEPDIR)/test-test_crypto_cgo.Tpo -c -o src/test/test-test_crypto_cgo.obj `if test -f 'src/test/test_crypto_cgo.c'; then $(CYGPATH_W) 'src/test/test_crypto_cgo.c'; else $(CYGPATH_W) '$(srcdir)/src/test/test_crypto_cgo.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/test/$(DEPDIR)/test-test_crypto_cgo.Tpo src/test/$(DEPDIR)/test-test_crypto_cgo.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/test/test_crypto_cgo.c' object='src/test/test-test_crypto_cgo.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_test_test_CPPFLAGS) $(CPPFLAGS) $(src_test_test_CFLAGS) $(CFLAGS) -c -o src/test/test-test_crypto_cgo.obj `if test -f 'src/test/test_crypto_cgo.c'; then $(CYGPATH_W) 'src/test/test_crypto_cgo.c'; else $(CYGPATH_W) '$(srcdir)/src/test/test_crypto_cgo.c'; fi` + src/test/test-test_data.o: src/test/test_data.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_test_test_CPPFLAGS) $(CPPFLAGS) $(src_test_test_CFLAGS) $(CFLAGS) -MT src/test/test-test_data.o -MD -MP -MF src/test/$(DEPDIR)/test-test_data.Tpo -c -o src/test/test-test_data.o `test -f 'src/test/test_data.c' || echo '$(srcdir)/'`src/test/test_data.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/test/$(DEPDIR)/test-test_data.Tpo src/test/$(DEPDIR)/test-test_data.Po @@ -24108,6 +24299,8 @@ -rm -f src/ext/keccak-tiny/$(am__dirstamp) -rm -f src/ext/mulodi/$(DEPDIR)/$(am__dirstamp) -rm -f src/ext/mulodi/$(am__dirstamp) + -rm -f src/ext/polyval/$(DEPDIR)/$(am__dirstamp) + -rm -f src/ext/polyval/$(am__dirstamp) -rm -f src/ext/trunnel/$(DEPDIR)/$(am__dirstamp) -rm -f src/ext/trunnel/$(am__dirstamp) -rm -f src/feature/api/$(DEPDIR)/$(am__dirstamp) @@ -24267,14 +24460,16 @@ -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_fast.Po -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_ntor.Po -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_ntor_v3.Po - -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_tap.Po -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto.Po + -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_cgo.Po + -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_tor1.Po -rm -f src/core/crypto/$(DEPDIR)/onion_crypto.Po -rm -f src/core/crypto/$(DEPDIR)/onion_fast.Po -rm -f src/core/crypto/$(DEPDIR)/onion_ntor.Po -rm -f src/core/crypto/$(DEPDIR)/onion_ntor_v3.Po - -rm -f src/core/crypto/$(DEPDIR)/onion_tap.Po -rm -f src/core/crypto/$(DEPDIR)/relay_crypto.Po + -rm -f src/core/crypto/$(DEPDIR)/relay_crypto_cgo.Po + -rm -f src/core/crypto/$(DEPDIR)/relay_crypto_tor1.Po -rm -f src/core/mainloop/$(DEPDIR)/connection.Po -rm -f src/core/mainloop/$(DEPDIR)/cpuworker.Po -rm -f src/core/mainloop/$(DEPDIR)/libtor_app_testing_a-connection.Po @@ -24356,6 +24551,7 @@ -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-protover.Po -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-reasons.Po -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-relay.Po + -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-relay_msg.Po -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler.Po -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler_kist.Po -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler_vanilla.Po @@ -24373,6 +24569,7 @@ -rm -f src/core/or/$(DEPDIR)/protover.Po -rm -f src/core/or/$(DEPDIR)/reasons.Po -rm -f src/core/or/$(DEPDIR)/relay.Po + -rm -f src/core/or/$(DEPDIR)/relay_msg.Po -rm -f src/core/or/$(DEPDIR)/scheduler.Po -rm -f src/core/or/$(DEPDIR)/scheduler_kist.Po -rm -f src/core/or/$(DEPDIR)/scheduler_vanilla.Po @@ -24462,6 +24659,7 @@ -rm -f src/ext/keccak-tiny/$(DEPDIR)/libkeccak_tiny_a-keccak-tiny-unrolled.Po -rm -f src/ext/mulodi/$(DEPDIR)/lib_libtor_ctime_a-mulodi4.Po -rm -f src/ext/mulodi/$(DEPDIR)/lib_libtor_ctime_testing_a-mulodi4.Po + -rm -f src/ext/polyval/$(DEPDIR)/libpolyval_a-polyval.Po -rm -f src/ext/trunnel/$(DEPDIR)/trunnel_libor_trunnel_a-trunnel.Po -rm -f src/ext/trunnel/$(DEPDIR)/trunnel_libor_trunnel_testing_a-trunnel.Po -rm -f src/feature/api/$(DEPDIR)/core_libtor_app_testing_a-tor_api.Po @@ -25071,6 +25269,7 @@ -rm -f src/test/$(DEPDIR)/test-test_controller.Po -rm -f src/test/$(DEPDIR)/test-test_controller_events.Po -rm -f src/test/$(DEPDIR)/test-test_crypto.Po + -rm -f src/test/$(DEPDIR)/test-test_crypto_cgo.Po -rm -f src/test/$(DEPDIR)/test-test_crypto_ope.Po -rm -f src/test/$(DEPDIR)/test-test_crypto_openssl.Po -rm -f src/test/$(DEPDIR)/test-test_crypto_rng.Po @@ -25294,6 +25493,7 @@ -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_a-pwbox.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_a-sendme_cell.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_a-socks5.Po + -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_a-subproto_request.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-channelpadding_negotiation.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-circpad_negotiation.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-conflux.Po @@ -25306,6 +25506,7 @@ -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-pwbox.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-sendme_cell.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-socks5.Po + -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-subproto_request.Po -rm -f src/trunnel/hs/$(DEPDIR)/libor_trunnel_a-cell_establish_intro.Po -rm -f src/trunnel/hs/$(DEPDIR)/libor_trunnel_a-cell_introduce1.Po -rm -f src/trunnel/hs/$(DEPDIR)/libor_trunnel_a-cell_rendezvous.Po @@ -25388,14 +25589,16 @@ -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_fast.Po -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_ntor.Po -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_ntor_v3.Po - -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-onion_tap.Po -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto.Po + -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_cgo.Po + -rm -f src/core/crypto/$(DEPDIR)/libtor_app_testing_a-relay_crypto_tor1.Po -rm -f src/core/crypto/$(DEPDIR)/onion_crypto.Po -rm -f src/core/crypto/$(DEPDIR)/onion_fast.Po -rm -f src/core/crypto/$(DEPDIR)/onion_ntor.Po -rm -f src/core/crypto/$(DEPDIR)/onion_ntor_v3.Po - -rm -f src/core/crypto/$(DEPDIR)/onion_tap.Po -rm -f src/core/crypto/$(DEPDIR)/relay_crypto.Po + -rm -f src/core/crypto/$(DEPDIR)/relay_crypto_cgo.Po + -rm -f src/core/crypto/$(DEPDIR)/relay_crypto_tor1.Po -rm -f src/core/mainloop/$(DEPDIR)/connection.Po -rm -f src/core/mainloop/$(DEPDIR)/cpuworker.Po -rm -f src/core/mainloop/$(DEPDIR)/libtor_app_testing_a-connection.Po @@ -25477,6 +25680,7 @@ -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-protover.Po -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-reasons.Po -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-relay.Po + -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-relay_msg.Po -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler.Po -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler_kist.Po -rm -f src/core/or/$(DEPDIR)/libtor_app_testing_a-scheduler_vanilla.Po @@ -25494,6 +25698,7 @@ -rm -f src/core/or/$(DEPDIR)/protover.Po -rm -f src/core/or/$(DEPDIR)/reasons.Po -rm -f src/core/or/$(DEPDIR)/relay.Po + -rm -f src/core/or/$(DEPDIR)/relay_msg.Po -rm -f src/core/or/$(DEPDIR)/scheduler.Po -rm -f src/core/or/$(DEPDIR)/scheduler_kist.Po -rm -f src/core/or/$(DEPDIR)/scheduler_vanilla.Po @@ -25583,6 +25788,7 @@ -rm -f src/ext/keccak-tiny/$(DEPDIR)/libkeccak_tiny_a-keccak-tiny-unrolled.Po -rm -f src/ext/mulodi/$(DEPDIR)/lib_libtor_ctime_a-mulodi4.Po -rm -f src/ext/mulodi/$(DEPDIR)/lib_libtor_ctime_testing_a-mulodi4.Po + -rm -f src/ext/polyval/$(DEPDIR)/libpolyval_a-polyval.Po -rm -f src/ext/trunnel/$(DEPDIR)/trunnel_libor_trunnel_a-trunnel.Po -rm -f src/ext/trunnel/$(DEPDIR)/trunnel_libor_trunnel_testing_a-trunnel.Po -rm -f src/feature/api/$(DEPDIR)/core_libtor_app_testing_a-tor_api.Po @@ -26192,6 +26398,7 @@ -rm -f src/test/$(DEPDIR)/test-test_controller.Po -rm -f src/test/$(DEPDIR)/test-test_controller_events.Po -rm -f src/test/$(DEPDIR)/test-test_crypto.Po + -rm -f src/test/$(DEPDIR)/test-test_crypto_cgo.Po -rm -f src/test/$(DEPDIR)/test-test_crypto_ope.Po -rm -f src/test/$(DEPDIR)/test-test_crypto_openssl.Po -rm -f src/test/$(DEPDIR)/test-test_crypto_rng.Po @@ -26415,6 +26622,7 @@ -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_a-pwbox.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_a-sendme_cell.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_a-socks5.Po + -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_a-subproto_request.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-channelpadding_negotiation.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-circpad_negotiation.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-conflux.Po @@ -26427,6 +26635,7 @@ -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-pwbox.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-sendme_cell.Po -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-socks5.Po + -rm -f src/trunnel/$(DEPDIR)/libor_trunnel_testing_a-subproto_request.Po -rm -f src/trunnel/hs/$(DEPDIR)/libor_trunnel_a-cell_establish_intro.Po -rm -f src/trunnel/hs/$(DEPDIR)/libor_trunnel_a-cell_introduce1.Po -rm -f src/trunnel/hs/$(DEPDIR)/libor_trunnel_a-cell_rendezvous.Po diff -Nru tor-0.4.8.16/README.md tor-0.4.9.6/README.md --- tor-0.4.8.16/README.md 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/README.md 2026-03-25 14:30:34.000000000 +0000 @@ -58,13 +58,16 @@ Download new versions: -- https://www.torproject.org/download/download.html +- https://www.torproject.org/download/tor -Documentation, including links to installation and setup instructions: +How to verify Tor source: -- https://www.torproject.org/docs/documentation.html +- https://support.torproject.org/little-t-tor/ -Frequently Asked Questions: +Documentation and Frequently Asked Questions: -- https://www.torproject.org/docs/faq.html +- https://support.torproject.org/ +How to run a Tor relay: + +- https://community.torproject.org/relay/ diff -Nru tor-0.4.8.16/ReleaseNotes tor-0.4.9.6/ReleaseNotes --- tor-0.4.8.16/ReleaseNotes 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/ReleaseNotes 2026-03-25 14:30:34.000000000 +0000 @@ -2,10 +2,531 @@ release of Tor. If you want to see more detailed descriptions of the changes in each development snapshot, see the ChangeLog file. +Changes in version 0.4.9.6 - 2026-03-25 + This is a security release fixing major bugfixes that could possibly lead to + remote crashing relays. We strongly recommend upgrading as soon as possible. + + o Major bugfix (security): + - Fix a stack overflow of 11 bytes on malicious CREATED2. This lead + to a remote crash. TROVE-2026-003. Reported-by: Anas Cherni of + Calif.io. Fixes bug 41231; bugfix on 0.4.9.1-alpha. + + o Major bugfix (security, conflux): + - Fix a memory compare using the wrong length. This could lead to a + remote crash when using the conflux subsystem. TROVE-2026-004. + Fixes bug 41232; bugfix on 0.4.8.1-alpha. + + o Minor bugfixes (security): + - Fix a series of defense in depth security issues found across the + codebase. Fixes bug 41228; bugfix on 0.3.5.1-alpha. + + o Minor bugfixes (portability): + - (Hopefully) fix our polyval implementation on big-endian + platforms. Fixes bug 41215; bugfix on 0.4.9.3-alpha. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on March 25, 2026. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2026/03/25. + + +Changes in version 0.4.9.5 - 2026-02-12 + This first stable release in the 0.4.9 series introduces a new + circuit-level encryption design for better client security, as well + as a more scalable way for large relay operators to annotate which + relays they run so clients can avoid using too many of them in a + single circuit. + + o Major features (cryptography): + - Clients and relays can now negotiate Counter Galois Onion (CGO) + relay cryptography, as designed by Jean Paul Degabriele, + Alessandro Melloni, Jean-Pierre Münch, and Martijn Stam. CGO + provides improved resistance to several kinds of tagging attacks, + better forward secrecy, and better forgery resistance. Closes + ticket 41047. Implements proposal 359. + + o Major features (path selection): + - Clients and relays now support "happy families", a system to + simplify relay family operation and improve directory performance. + With "happy families", relays in a family share a secret "family + key", which they use to prove their membership in the family. + Implements proposal 321; closes ticket 41009. Note that until + enough clients are upgraded, relay operators will still need to + configure MyFamily lists. But once clients no longer depend on + those lists, we will be able to remove them entirely, thereby + simplifying family operation, and making microdescriptor downloads + approximately 80% smaller. For more information, see + https://community.torproject.org/relay/setup/post-install/family-ids/ + + o Major bugfixes (conflux): + - Ensure conflux guards obey family and subnet restrictions. Fixes + bug 40976; bugfix on 0.4.8.1-alpha. + + o Major bugfixes (controller events): + - Fix spikes occurring in bandwidth cache events on control connection. + Fixes bug 31524; bugfix on 0.0.9pre5. + + o Major bugfixes (sandbox): + - Fix sandbox to work on architectures that use Linux's generic + syscall interface, extending support for AArch64 (ARM64) and + adding support for RISC-V, allowing test_include.sh and the + sandbox unit tests to pass on these systems even when building + with fragile hardening enabled. Fixes bugs 40465 and 40599; bugfix + on 0.2.5.1-alpha. + + o Minor features (client security, reliability): + - When KeepaliveIsolateSOCKSAuth is keeping a circuit alive, expire + the circuit based on when it was last in use for any stream, not + (as we did before) based on when a stream was last attached to it. + Closes ticket 41157. Implements a minimal version of Proposal 368. + + o Minor features (exit relays): + - Implement reevaluating new exit policy against existing + connections. This is controlled by new config option + ReevaluateExitPolicy, defaulting to 0. Closes ticket 40676. + - Implement a token-bucket based rate limiter for stream creation + and resolve request. It is configured by the DoSStream* family of + configuration options. Closes ticket 40736. + - Add Monero ports to the ReducedExitPolicy. Closes ticket 41168. + + o Minor features (bridges): + - Save complete bridge lines to 'datadir/bridgelines'. Closes + ticket 29128. + + o Minor features (client extensibility): + - Implement new HTTPTunnelPort features for interoperability with + Arti's HTTP CONNECT proxy. This work adds new headers to requests + to and replies from the HttpConnectPort, support for OPTIONS + requests, tightens the expected syntax for Proxy-Authorization, + and increases defense-in-depth against some kinds of cross-site + HTTP attacks. Closes ticket 41156. Implements proposal 365. + - Detect invalid SOCKS5 username/password combinations according to + new extended parameters syntax. (Currently, this rejects any + SOCKS5 username beginning with "", except for the username + "0". Such usernames are now reserved to communicate + additional parameters with other Tor implementations.) Implements + proposal 351. + + o Minor features (sandboxing): + - Allow the fstatat64 and statx syscalls on i386 architecture when + glibc >= 2.33. On i386, glibc uses fstatat64 instead of newfstatat + for stat operations, and statx for time64 support. Without this, + SIGHUP configuration reload fails when using sandbox mode with + %include directives on i386 with Debian Bookworm or newer. + - Allow the lstat64 syscall on i386 architecture. This syscall is + used by glob() in glibc 2.36+ when processing %include directives + with directory patterns. + + o Minor features (security): + - Increase the size of our finite-field Diffie Hellman TLS group + (which we should never actually use!) to 2048 bits. Part of + ticket 41067. + - Require TLS version 1.2 or later. (Version 1.3 support will be + required in the near future.) Part of ticket 41067. + - Update TLS 1.2 client cipher list to match current Firefox. Part + of ticket 41067. + - Verify needle is smaller than haystack before calling memmem. + Closes ticket 40854. + + o Minor features (onion services): + - Add 3 more keywords to the ADD_ONION control command: + PoWDefensesEnabled, PoWQueueRate and PoWQueueBurst which correspond + to HiddenServicePoWDefensesEnabled, HiddenServicePoWQueueRate and + HiddenServicePoWQueueBurst from torrc. + - Reduce the minimum value of hsdir_interval to match recent tor- + spec change. + + o Minor feature (directory authority): + - Introduce MinimalAcceptedServerVersion to allow configuring + the minimum accepted relay version without requiring a new tor + release. Closes ticket 40817. + + o Minor features (metrics port): + - New metrics on the MetricsPort for the number of BUG() calls that + occurred at runtime. Fixes bugs 40839 and 41104; bugfix on + 0.4.7.1-alpha. + - Handle rephist tracking of ntor and ntor_v3 handshakes + individually such that MetricsPort exposes the correct values. + Fixes bug 40638; bugfix on 0.4.7.11. + - Add new metrics for relays on the MetricsPort namely the count of + drop cell, destroy cell and the number of circuit protocol + violation seen that lead to a circuit close. Closes ticket 40816. + + o Minor features (forward-compatibility): + - We now correctly parse microdescriptors and router descriptors + that do not include TAP onion keys. (For backward compatibility, + authorities continue to require these keys.) Implements part of + proposal 350. + + o Minor features (portability, android): + - Use /data/local/tmp for data storage on Android by default. Closes + ticket 40487. Patch from Hans-Christoph Steiner. + + o Minor features (directory authority): + - Export unsigned consensus documents once we have seen a threshold + of signatures, as a step toward the consensus transparency + experiment. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on February 12, 2026. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, + as retrieved on 2026/02/12. + + o Minor features (windows): + - Various compilation fixes for our Windows CI. Closes ticket 41214. + + o Minor bugfixes (exit relays): + - Clip every returned DNS TTL to 60 (RESOLVED) in order to mitigate + an exit DNS cache oracle. Fixes bug 40979; bugfix on 0.3.5.1-alpha. + + o Minor bugfixes (spec conformance): + - Set the length field correctly on RELAY_COMMAND_CONFLUX_SWITCH + messages. Previously, it was always set to the maximum value. + Fixes bug 41056; bugfix on 0.4.8.1-alpha. + - Do not treat "15" as a recognized remote END reason code. + Formerly, we treated it as synonymous with a local ENTRYPOLICY, + which isn't a valid remote code at all. Fixes bug 41171; bugfix + on 0.2.0.8-alpha. + + o Minor bugfixes (tooling): + - Fix a false positive valgrind related to inspecting a bitfield + next to another uninitialized bitfield. Fixes bug 41182; bugfix + on 0.3.3.2-alpha. + - Fix minor warnings from newer versions of shellcheck and clang. + Fixes bug 41166; bugfix on 0.4.3.1-alpha and several + other versions. + - Fix a warning when compiling with GCC 14.2. Closes 41032. + + o Minor bugfixes (threads): + - Make thread control POSIX compliant. Fixes bug 41109; bugfix + on 0.4.8.17. + + o Minor bugfix (client DNS): + - Handle empty DNS reply without sending back an error and instead + send back NOERROR (RFC1035 error code 0x0). Fixes bug 40248; + bugfix on 0.3.5.1-alpha. + + o Minor bugfixes (directory authorities): + - After we added layer-two vanguards, directory authorities wouldn't + think any of their vanguards were suitable for circuits, leading + to a "Failed to find node for hop #2 of our path. Discarding this + circuit." log message once per second from startup until they made + a fresh consensus. Now they look to their existing consensus on + startup, letting them build circuits properly from the beginning. + Fixes bug 40802; bugfix on 0.4.7.1-alpha. + + o Minor bugfixes (tests): + - Fix a test failure with OpenSSL builds running at security level 1 + or greater, which does not permit SHA-1 certificates. Fixes bug + 41021; bugfix on 0.2.8.1-alpha. + + o Minor bugfixes (bridges): + - Don't warn when BridgeRelay is 1 and ExitRelay is explicitly set + to 0. Fixes bug 40884; bugfix on 0.4.8.3-rc. + + o Minor bugfixes (conflux, client): + - Avoid a non fatal assert caused by data coming in on a conflux set + that is being freed during shutdown. Fixes bug 40870; bugfix + on 0.4.8.1-alpha. + + o Minor bugfixes (testing network): + - Enabling TestingTorNetwork no longer forces fast hidden service + intro point rotation. This reduces noise and errors when using + hidden services with TestingTorNetwork enabled. Fixes bug 40922; + bugfix on 0.3.2.1-alpha. + + o Minor bugfixes (relay): + - Refuse to overwrite an existing *.secret_family_key when running + tor --keygen-family. Fixes bug 41184; bugfix on 0.4.9.1-alpha. + + o New system requirements: + - When built with LibreSSL, Tor now requires LibreSSL 3.7 or later. + Part of ticket 41059. + - When built with OpenSSL, Tor now requires OpenSSL 1.1.1 or later. + (We strongly recommend 3.0 or later, but still build with 1.1.1, + even though it is not supported by the OpenSSL team, due to its + presence in Debian oldstable.) Part of ticket 41059. + + o Removed features (relays): + - Relays no longer support clients that falsely advertise TLS + ciphers they don't really support. (Clients have not done this + since 0.2.3.17-beta). Part of ticket 41031. + - Relays no longer support clients that require obsolete v1 and v2 + link handshakes. (The v3 link handshake has been supported since + 0.2.3.6-alpha). Part of ticket 41031. + - Relays no longer support the obsolete TAP circuit extension + protocol. (For backward compatibility, however, relays still + continue to include TAP keys in their descriptors.) Implements + part of proposal 350. + - Relays no longer support the obsolete "RSA-SHA256-TLSSecret" + authentication method, which used a dangerously short RSA key, and + which required access TLS session internals. The current method + ("Ed25519-SHA256-RFC5705") has been supported since 0.3.0.1-alpha. + Closes ticket 41020. + + o Removed features (directory authorities): + - Directory authorities no longer support consensus methods before + method 32. Closes ticket 40835. + - We include a new consensus method that removes support for + computing "package" lines in consensus documents. This feature was + never used, and support for including it in our votes was removed + in 0.4.2.1-alpha. Finishes implementation of proposal 301. + + +Changes in version 0.4.8.22 - 2026-01-28 + This is likely the very last release of the 0.4.8.x series. Three major + bugfixes detailed below including two affecting directory servers (basically + all relays). We strongly recommend upgrading as soon as possible. + + o Major bugfixes (security): + - Avoid an out-of-bounds read error that could occur with + V1-formatted EXTEND cells. Fixes bug 41180; bugfix on 0.4.8.1-alpha. + This is tracked as TROVE-2025-016. + + o Major bugfixes (directory servers): + - Allow old clients to fetch the consensus even if they use version + 0 of the SENDME protocol. In mid 2025 we changed the required + minimum version of the "FlowCtrl" protocol to 1, meaning directory + caches hang up on clients that send a version 0 SENDME cell. Since + old clients were no longer able to retrieve the consensus, they + couldn't learn about this required minimum version -- meaning + we've had many many old clients loading down directory servers for + the past months. Fixes bug 41191; bugfix on 0.4.1.1-alpha. + - Don't count networkstatus serves until they finish. When we + started serving a consensus document but the client didn't receive + all of it, we were still counting that as a success in our stats. + This mistake, which can be triggered for example by obsolete + clients or by DPI-based censorship, led to wildly inflated user + counts because we estimate total users in the world based on + successful consensus fetches. Fixes bug 41192; bugfix + on 0.2.1.1-alpha. + + o Minor feature (testing, CI): + - Bump the CI version of chutney to the current version as of + 2026-01-21 (3338f5c). + + o Minor features (debugging, compression): + - Do not check for compression bombs for buffers smaller than 5MB + (increased from 64 KB). Fixes ticket 40739; bugfix on 0.2.1.29. + + o Minor features (directory servers): + - Track how many times directory servers begin serving networkstatus + documents, so we can compare it to the number of times we finish + serving them. Motivated by the fixes in ticket 41192. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on January 28, 2026. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2026/01/28. + + o Minor bugfixes (relay): + - Downgrade "Error relaying cell across rendezvous" log warn to info + as the error condition is possible under normal circumstances. Fixes + bug 40951; bugfix on 0.3.5.1-alpha. + + o Code simplification and refactoring: + - Simplify SOCKS4a parsing to avoid the (false) appearance of + integer underflows, and to make the logic more obvious. Fixes bug + 41190; bugfix on 0.3.5.1-alpha. + + +Changes in version 0.4.8.21 - 2025-11-17 + This release is a continuation of the previous one and addresses additional + Conflux-related issues identified through further testing and feedback from + relay operators. We strongly recommend upgrading as soon as possible. + + o Major bugfixes (conflux, exit): + - When dequeuing out-of-order conflux cells, the circuit could be + closed in between two dequeues, which could lead to mishandling + a NULL pointer. Fixes bug 41162; bugfix on 0.4.8.4. + + o Minor feature (compiler flag): + - Add -mbranch-protection=standard for arm64. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on November 17, 2025. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/11/17. + + o Minor bugfixes (bridges, pluggable transport): + - Fix a bug causing the initial tor process to hang instead of + exiting with RunAsDaemon, when pluggable transports are used. + Fixes bug 41088; bugfix on 0.4.8.1-alpha. + + +Changes in version 0.4.8.20 - 2025-11-10 + This release fixes several bugs related to Conflux edge cases as well as + adding a new hardening compiler flag if supported. + + o Minor feature (compiler flag): + - Add -fcf-protection=full if supported by the compiler. + Implements ticket 41139. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on November 10, 2025. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/11/10. + + o Minor bugfixes (conflux fragile asserts): + - Fix the root cause of some conflux fragile asserts when a control + port listener is attached. Fixes bug 41037; bugfix on 0.4.8.16. + + o Minor bugfixes (conflux, relay): + - Fix a series of conflux edge cases about sequence number + arithmetic and OOM handler kicking in under heavy memory pressure. + Fixes bug 41155; bugfix on 0.4.8.4. + + +Changes in version 0.4.8.19 - 2025-10-06 + This release provides major bugfixes for a LibreSSL issue and a flow control + C-tor specific problem (not protocol). We strongly recommend you upgrade as + soon as possible. + + o Major bugfixes (client, TLS): + - Fix some clients not being able to connect to LibreSSL relays. + Fixes bug 41134; bugfix on 0.4.8.17. + + o Minor bugfixes (stream flow control performance): + - Use a 5 ms grace period to allow an edge connection to flush its + stream data to the socket before sending an XOFF. This + significantly reduces the number of XON/XOFF messages sent when + (1) the application is reading stream data at a fast rate, and (2) + conflux is enabled. Fixes part of bug 41130; bugfix on 0.4.7.2-alpha. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on October 06, 2025. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/10/06. + + o Minor bugfix (process): + - Avoid closing all possible FDs when spawning a process (PT). On + some systems, this could lead to 3+ minutes hang. Fixes bug 40990; + bugfix on 0.3.5.1-alpha. + + +Changes in version 0.4.8.18 - 2025-09-16 + This is a minor release with a major onion service directory cache (HSDir) + bug fix. A series of minor bugfixes as well. As always, we strongly recommend + to upgrade as soon as possible. + + o Major bugfixes (onion service directory cache): + - Preserve the download counter of an onion service descriptor + across descriptor uploads, so that recently updated descriptors + don't get pruned if there is memory pressure soon after update. + Additionally, create a separate torrc option MaxHSDirCacheBytes + that defaults to the former 20% of MaxMemInQueues threshold, but + can be controlled by relay operators under DoS. Also enforce this + threshold during HSDir uploads. Fixes bug 41006; bugfix + on 0.4.8.14. + + o Minor feature (padding, logging): + - Reduce the amount of messages being logged related to channel + padding timeout when log level is "notice". + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on September 16, 2025. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/09/16. + + o Minor bugfix (conflux): + - Remove the pending nonce if we realize that the nonce of the + unlinked circuit is not tracked anymore. Should avoid the non + fatal assert triggered with a control port circuit event. Fixes + bug 41037; bugfix on 0.4.8.15. + + o Minor bugfixes (circuit handling): + - Prevent circuit_mark_for_close() from being called twice on the + same circuit. Second fix attempt Fixes bug 41106; bugfix + on 0.4.8.17. + + +Changes in version 0.4.8.17 - 2025-06-30 + This is a minor providing a series of minor features especially in the realm + of TLS. It also brings a new set of recommended and required sub protocols. + And finally, few minor bugfixes, nothing major. As always, we strongly + recommend you upgrade as soon as possible. + + o Minor features (security, TLS): + - When we are running with OpenSSL 3.5.0 or later, support using the + ML-KEM768 for post-quantum key agreement. Closes ticket 41041. + + o Minor feature (client, TLS): + - Set the TLS 1.3 cipher list instead of falling back on the + default value. + + o Minor features (fallbackdir): + - Regenerate fallback directories generated on June 30, 2025. + + o Minor features (geoip data): + - Update the geoip files to match the IPFire Location Database, as + retrieved on 2025/06/30. + + o Minor features (hsdesc POW): + - Tolerate multiple PoW schemes in onion service descriptors, for + future extensibility. Implements torspec ticket 272. + + o Minor features (performance TLS): + - When running with with OpenSSL 3.0.0 or later, support using + X25519 for TLS key agreement. (This should slightly improve + performance for TLS session establishment.) + + o Minor features (portability): + - Fix warnings when compiling with GCC 15. Closes ticket 41079. + + o Minor features (recommended protocols): + - Directory authorities now vote to recommend that clients support + certain protocols beyond those that are required. These include + improved support for connecting to relays on IPv6, NtorV3, and + congestion control. Part of ticket 40836. + + o Minor features (required protocols): + - Directory authorities now vote to require clients to support the + authenticated SENDME feature, which was introduced in + 0.4.1.1-alpha. Part of ticket 40836. + - Directory authorities now vote to require relays to support + certain protocols, all of which have been implemented since + 0.4.7.4-alpha or earlier. These include improved support for + connecting to relays on IPv6, NtorV3, running as a rate-limited + introduction point, authenticated SENDMEs, and congestion control. + Part of ticket 40836. + + o Minor bugfix (conflux): + - Avoid a non fatal assert when describing a conflux circuit on the + control port after being prepped to be freed. Fixes bug 41037; + bugfix on 0.4.8.15. + + o Minor bugfixes (circuit handling): + - Prevent circuit_mark_for_close() from being called twice on the + same circuit. Fixes bug 40951; bugfix on 0.4.8.16-dev. + + o Minor bugfixes (compiler warnings): + - Make sure the two bitfields in the half-closed edge struct are + unsigned, as we're using them for boolean values and assign 1 to + them. Fixes bug 40911; bugfix on 0.4.7.2-alpha. + + o Minor bugfixes (threads, memory): + - Improvements in cleanup of resources used by threads. Fixes bug + 40991; bugfix on 0.4.8.13-dev. + - Rework start and exit of worker threads. + + Changes in version 0.4.8.16 - 2025-03-24 - This is quick second release since 0.4.8.15 due to a typo in a directory - authority rule file. This only affects directory authorities. Regardless, - upgrading to latest stable is always desired. + This is a quick second release since 0.4.8.15 due to a typo in a directory + authority rule file. This only affects directory authorities. o Minor features (geoip data): - Update the geoip files to match the IPFire Location Database, as @@ -13,13 +534,13 @@ o Minor bugfix (dirauth): - Fix typo in flag assignment approved-routers file. Fixes bug - 41035; bugfix on 0.4.8.15 + 41035; bugfix on 0.4.8.15. Changes in version 0.4.8.15 - 2025-03-20 This is a minor release fixing a sandbox issue for bandwidth authority and a conflux issue on the control port. It also has a client fix about relay flag - usage. We strongly recommend to update as soon as possible as usual. + usage. o Minor feature (testing, CI): - Use a fixed version of chutney (be881a1e) instead of its current @@ -37,18 +558,18 @@ retrieved on 2025/03/20. o Minor bugfixes (control port): - - Correctly report conflux pair information to controller fields - Fixes bug 40872; bugfix on 0.4.8.1-alpha + - Correctly report conflux pair information to controller fields. + Fixes bug 40872; bugfix on 0.4.8.1-alpha. o Minor bugfixes (relay flag usage): - Fix client usage of the MiddleOnly flag so that MiddleOnly relays are not used as HS IP or RP by clients or services. Additionally, give dirauths the ability to remove specific flags, as an - alternative to MiddleOnly. Fixes bug 41023; bugfix on 0.4.7.2-alpha + alternative to MiddleOnly. Fixes bug 41023; bugfix on 0.4.7.2-alpha. o Minor bugfixes (sandbox, bwauth): - Fix sandbox to work for bandwidth authority. Fixes bug 40933; - bugfix on 0.2.2.1-alpha + bugfix on 0.2.2.1-alpha. Changes in version 0.4.8.14 - 2025-02-05 @@ -80,8 +601,8 @@ Changes in version 0.4.8.13 - 2024-10-24 - This is minor release fixing an important client circuit building (Conflux - related) bug which lead to performance degradation and extra load on the + This minor release fixes an important client circuit building (conflux + related) bug which led to performance degradation and extra load on the network. Some minor memory leaks fixes as well as an important minor feature for pluggable transports. We strongly recommend to update as soon as possible for clients in order to neutralize this conflux bug. @@ -94,7 +615,7 @@ which added overall load to the network, used bandwidth and battery from clients that weren't actively using their Tor, and kept sockets open on guards which added connection padding - essentially forever. Fixes bug 40981; bugfix on 0.4.8.1-alpha; + essentially forever. Fixes bug 40981; bugfix on 0.4.8.1-alpha. o Minor feature (bridges, pluggable transport): - Add STATUS TYPE=version handler for Pluggable Transport. This @@ -148,11 +669,11 @@ Changes in version 0.4.8.11 - 2024-04-10 - This is a minor release mostly to upgrade the fallbackdir list. Worth noting - also that directory authority running this version will now automatically + This is a minor release mostly to upgrade the fallbackdir list. + Directory authorities running this version will now automatically reject relays running the end of life 0.4.7.x version. - o Minor feature (authority): + o Minor features (directory authorities): - Reject 0.4.7.x series at the authority level. Closes ticket 40896. o Minor feature (dirauth, tor26): @@ -185,7 +706,7 @@ o Major bugfixes (TROVE-2023-007, exit): - Improper error propagation from a safety check in conflux leg - linking lead to a desynchronization of which legs were part of a + linking led to a desynchronization of which legs were part of a conflux set, ultimately causing a UAF and NULL pointer dereference crash on Exit relays. Fixes bug 40897; bugfix on 0.4.8.1-alpha. @@ -197,8 +718,8 @@ retrieved on 2023/12/08. o Minor bugfixes (bridges, statistics): - - Correctly report statistics for client count over Pluggable - transport. Fixes bug 40871; bugfix on 0.4.8.4 + - Correctly report statistics for client count over pluggable + transports. Fixes bug 40871; bugfix on 0.4.8.4. Changes in version 0.4.8.9 - 2023-11-09 @@ -220,7 +741,7 @@ o Major bugfixes (onion service, TROVE-2023-006): - Fix a possible hard assert on a NULL pointer when recording a failed rendezvous circuit on the service side for the MetricsPort. - Fixes bug 40883; bugfix on 0.4.8.1-alpha + Fixes bug 40883; bugfix on 0.4.8.1-alpha. o Minor features (fallbackdir): - Regenerate fallback directories generated on November 09, 2023. @@ -233,7 +754,7 @@ Changes in version 0.4.8.8 - 2023-11-03 We are releasing today a fix for a high security issue, TROVE-2023-004, that is affecting relays. Also a few minor bugfixes detailed below. Please upgrade - as soon as posssible. + as soon as possible. o Major bugfixes (TROVE-2023-004, relay): - Mitigate an issue when Tor compiled with OpenSSL can crash during @@ -276,6 +797,11 @@ Changes in version 0.4.8.6 - 2023-09-18 + This version contains an important fix for onion services regarding + congestion control and its reliability. Apart from that, unneeded BUG + warnings have been suppressed especially about a compression bomb seen + on relays. + o Major bugfixes (onion service): - Fix a reliability issue where services were expiring their introduction points every consensus update. This caused @@ -420,8 +946,8 @@ o Minor features (testing): - All Rust code is now linted (cargo clippy) as part of GitLab CI, and - existing warnings have been fixed. - Any unit tests written in Rust now - run as part of GitLab CI. + existing warnings have been fixed. + - Any unit tests written in Rust now run as part of GitLab CI. o Minor feature (CI): - Update CI to use Debian Bullseye for runners. @@ -550,7 +1076,7 @@ o Minor bugfixes (conflux): - Count leg launch attempts prior to attempting to launch them. This - avoids inifinite launch attempts due to internal circuit building + avoids infinite launch attempts due to internal circuit building failures. Additionally, double-check that we have enough exits in our consensus overall, before attempting to launch conflux sets. Fixes bug 40811; bugfix on 0.4.8.1-alpha. @@ -631,7 +1157,7 @@ o Major bugfixes (congestion control): - Avoid incrementing the congestion window when the window is not - fully in use. Thia prevents overshoot in cases where long periods + fully in use. This prevents overshoot in cases where long periods of low activity would allow our congestion window to grow, and then get followed by a burst, which would cause queue overload. Also improve the increment checks for RFC3742. Fixes bug 40732; @@ -1222,7 +1748,7 @@ Exit, Guard, HSDir, and V2Dir; and in favor of BadExit. Implements part of proposal 335. Based on a patch from Neel Chauhan. - o Major features (Proposal 332, onion services, guard selection algorithm): + o Major features (Proposal 333, onion services, guard selection algorithm): - Clients and onion services now choose four long-lived "layer 2" guard relays for use as the middle hop in all onion circuits. These relays are kept in place for a randomized duration averaging diff -Nru tor-0.4.8.16/acinclude.m4 tor-0.4.9.6/acinclude.m4 --- tor-0.4.8.16/acinclude.m4 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/acinclude.m4 2026-03-25 14:30:34.000000000 +0000 @@ -9,6 +9,8 @@ [ if test -d "$1/lib"; then LDFLAGS="-L$1/lib $LDFLAGS" + elif test -d "$1/lib64"; then + LDFLAGS="-L$1/lib64 $LDFLAGS" else LDFLAGS="-L$1 $LDFLAGS" fi @@ -28,6 +30,9 @@ if test -d "$1/lib"; then TOR_LDFLAGS_$2="-L$1/lib" TOR_LIBDIR_$2="$1/lib" + elif test -d "$1/lib64"; then + TOR_LDFLAGS_$2="-L$1/lib64" + TOR_LIBDIR_$2="$1/lib64" else TOR_LDFLAGS_$2="-L$1" TOR_LIBDIR_$2="$1" diff -Nru tor-0.4.8.16/configure tor-0.4.9.6/configure --- tor-0.4.8.16/configure 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/configure 2026-03-25 14:30:34.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for tor 0.4.8.16. +# Generated by GNU Autoconf 2.69 for tor 0.4.9.6. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -577,8 +577,8 @@ # Identity of this package. PACKAGE_NAME='tor' PACKAGE_TARNAME='tor' -PACKAGE_VERSION='0.4.8.16' -PACKAGE_STRING='tor 0.4.8.16' +PACKAGE_VERSION='0.4.9.6' +PACKAGE_STRING='tor 0.4.9.6' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1473,7 +1473,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures tor 0.4.8.16 to adapt to many kinds of systems. +\`configure' configures tor 0.4.9.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1543,7 +1543,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of tor 0.4.8.16:";; + short | recursive ) echo "Configuration of tor 0.4.9.6:";; esac cat <<\_ACEOF @@ -1765,7 +1765,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -tor configure 0.4.8.16 +tor configure 0.4.9.6 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2470,7 +2470,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by tor $as_me 0.4.8.16, which was +It was created by tor $as_me 0.4.9.6, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2836,7 +2836,7 @@ # only shuts down for missing "required protocols" when those protocols # are listed as required by a consensus after this date. -$as_echo "#define APPROX_RELEASE_DATE \"2025-03-24\"" >>confdefs.h +$as_echo "#define APPROX_RELEASE_DATE \"2026-03-25\"" >>confdefs.h # "foreign" means we don't follow GNU package layout standards @@ -3357,7 +3357,7 @@ # Define the identity of the package. PACKAGE='tor' - VERSION='0.4.8.16' + VERSION='0.4.9.6' cat >>confdefs.h <<_ACEOF @@ -8977,6 +8977,41 @@ fi +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -Werror" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__((nonstring))" >&5 +$as_echo_n "checking for __attribute__((nonstring))... " >&6; } +if ${tor_cv_c_attr_nonstring+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + __attribute__((nonstring)) const char foo[5] = "abcde"; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tor_cv_c_attr_nonstring=yes +else + tor_cv_c_attr_nonstring=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tor_cv_c_attr_nonstring" >&5 +$as_echo "$tor_cv_c_attr_nonstring" >&6; } +CFLAGS="$saved_CFLAGS" + +if test "$tor_cv_c_attr_nonstring" = "yes"; then + +$as_echo "#define HAVE_ATTR_NONSTRING 1" >>confdefs.h + +fi + TORUSER=_tor # Check whether --with-tor-user was given. @@ -10209,6 +10244,8 @@ if test -d "$tor_trydir/lib"; then LDFLAGS="-L$tor_trydir/lib $LDFLAGS" + elif test -d "$tor_trydir/lib64"; then + LDFLAGS="-L$tor_trydir/lib64 $LDFLAGS" else LDFLAGS="-L$tor_trydir $LDFLAGS" fi @@ -10377,6 +10414,8 @@ if test -d "$tor_cv_library_libevent_dir/lib"; then LDFLAGS="-L$tor_cv_library_libevent_dir/lib $LDFLAGS" + elif test -d "$tor_cv_library_libevent_dir/lib64"; then + LDFLAGS="-L$tor_cv_library_libevent_dir/lib64 $LDFLAGS" else LDFLAGS="-L$tor_cv_library_libevent_dir $LDFLAGS" fi @@ -10396,6 +10435,9 @@ if test -d "$tor_cv_library_libevent_dir/lib"; then TOR_LDFLAGS_libevent="-L$tor_cv_library_libevent_dir/lib" TOR_LIBDIR_libevent="$tor_cv_library_libevent_dir/lib" + elif test -d "$tor_cv_library_libevent_dir/lib64"; then + TOR_LDFLAGS_libevent="-L$tor_cv_library_libevent_dir/lib64" + TOR_LIBDIR_libevent="$tor_cv_library_libevent_dir/lib64" else TOR_LDFLAGS_libevent="-L$tor_cv_library_libevent_dir" TOR_LIBDIR_libevent="$tor_cv_library_libevent_dir" @@ -10859,6 +10901,35 @@ fi + + save_CFLAGS="$CFLAGS" + save_LIBS="$LIBS" + LIBS="$LIBS $NSS_LIBS" + CFLAGS="$CFLAGS $NSS_CFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NSS defines ssl_kea_ecdh_hybrid(_psk)" >&5 +$as_echo_n "checking whether NSS defines ssl_kea_ecdh_hybrid(_psk)... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + int v = (int) ssl_kea_ecdh_hybrid_psk; + int v2 = (int) ssl_kea_ecdh_hybrid; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; }; + +$as_echo "#define NSS_HAS_ECDH_HYBRID 1" >>confdefs.h + + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + LIBS="$save_LIBS" + CPPFLAGS="$save_CPPFLAGS" fi @@ -10881,8 +10952,8 @@ fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: Now, we'll look for OpenSSL >= 1.0.1" >&5 -$as_echo "$as_me: Now, we'll look for OpenSSL >= 1.0.1" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: Now, we'll look for OpenSSL." >&5 +$as_echo "$as_me: Now, we'll look for OpenSSL." >&6;} tryopenssldir="" @@ -10931,6 +11002,8 @@ if test -d "$tor_trydir/lib"; then LDFLAGS="-L$tor_trydir/lib $LDFLAGS" + elif test -d "$tor_trydir/lib64"; then + LDFLAGS="-L$tor_trydir/lib64 $LDFLAGS" else LDFLAGS="-L$tor_trydir $LDFLAGS" fi @@ -11080,6 +11153,8 @@ if test -d "$tor_cv_library_openssl_dir/lib"; then LDFLAGS="-L$tor_cv_library_openssl_dir/lib $LDFLAGS" + elif test -d "$tor_cv_library_openssl_dir/lib64"; then + LDFLAGS="-L$tor_cv_library_openssl_dir/lib64 $LDFLAGS" else LDFLAGS="-L$tor_cv_library_openssl_dir $LDFLAGS" fi @@ -11099,6 +11174,9 @@ if test -d "$tor_cv_library_openssl_dir/lib"; then TOR_LDFLAGS_openssl="-L$tor_cv_library_openssl_dir/lib" TOR_LIBDIR_openssl="$tor_cv_library_openssl_dir/lib" + elif test -d "$tor_cv_library_openssl_dir/lib64"; then + TOR_LDFLAGS_openssl="-L$tor_cv_library_openssl_dir/lib64" + TOR_LIBDIR_openssl="$tor_cv_library_openssl_dir/lib64" else TOR_LDFLAGS_openssl="-L$tor_cv_library_openssl_dir" TOR_LIBDIR_openssl="$tor_cv_library_openssl_dir" @@ -11221,14 +11299,35 @@ CPPFLAGS="$TOR_CPPFLAGS_openssl $CPPFLAGS" -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL >= 3.0.0" >&5 -$as_echo_n "checking for OpenSSL >= 3.0.0... " >&6; } +for ac_header in openssl/engine.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "openssl/engine.h" "ac_cv_header_openssl_engine_h" "$ac_includes_default" +if test "x$ac_cv_header_openssl_engine_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_ENGINE_H 1 +_ACEOF + +else + as_fn_error $? "Missing required header openssl/engine.h. + +On Debian/Ubuntu install: libssl-dev +On Fedora/RHEL install: openssl-devel-engine + +Then re-run configure." "$LINENO" 5 +fi + +done + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL implementation" >&5 +$as_echo_n "checking for OpenSSL implementation... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L -#error "you_have_version_3" +#if defined(LIBRESSL_VERSION_NUMBER) +#error "this is libressl, no worries" #endif int @@ -11240,25 +11339,30 @@ } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; }; + openssl_impl=openssl + { $as_echo "$as_me:${as_lineno-$LINENO}: result: OpenSSL" >&5 +$as_echo "OpenSSL" >&6; } $as_echo "#define OPENSSL_SUPPRESS_DEPRECATED 1" >>confdefs.h + +else + openssl_impl=libressl + { $as_echo "$as_me:${as_lineno-$LINENO}: result: LibreSSL" >&5 +$as_echo "LibreSSL" >&6; } + fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL < 1.0.1" >&5 -$as_echo_n "checking for OpenSSL < 1.0.1... " >&6; } +if test "x$openssl_impl" = "xopenssl"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL < 1.1.1" >&5 +$as_echo_n "checking for OpenSSL < 1.1.1... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#if OPENSSL_VERSION_NUMBER < 0x1000100fL -#error "too old" +#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10101000L +#error "openssl too old" #endif int @@ -11273,20 +11377,23 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else - as_fn_error $? "OpenSSL is too old. We require 1.0.1 or later. You can specify a path to a newer one with --with-openssl-dir." "$LINENO" 5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + as_fn_error $? "Your version of OpenSSL is too old. We require 1.1.1 or later, and you should use 3.5 if possible." "$LINENO" 5 + fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether LibreSSL TLS 1.3 APIs are busted" >&5 -$as_echo_n "checking whether LibreSSL TLS 1.3 APIs are busted... " >&6; } +if test "x$openssl_impl" = "xlibressl"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LibreSSL < 3.7.0" >&5 +$as_echo_n "checking for LibreSSL < 3.7.0... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#if defined(LIBRESSL_VERSION_NUMBER) && \ - LIBRESSL_VERSION_NUMBER >= 0x3020100fL && \ - LIBRESSL_VERSION_NUMBER < 0x3040100fL -#error "oh no" +#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3070000fL +#error "libressl too old" #endif int @@ -11301,9 +11408,13 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else - as_fn_error $? "This version of LibreSSL won't work with Tor. Please upgrade to LibreSSL 3.4.1 or later. (Or downgrade to 3.2.0 if you really must.)" "$LINENO" 5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + as_fn_error $? "Your version of LibreSSL is too old. We require 3.7.0 or later." "$LINENO" 5 + fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11377,30 +11488,10 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $openssl_ver_mismatch" >&5 $as_echo "$openssl_ver_mismatch" >&6; } -ac_fn_c_check_member "$LINENO" "struct ssl_method_st" "get_cipher_by_char" "ac_cv_member_struct_ssl_method_st_get_cipher_by_char" "#include - -" -if test "x$ac_cv_member_struct_ssl_method_st_get_cipher_by_char" = xyes; then : - -cat >>confdefs.h <<_ACEOF -#define HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR 1 -_ACEOF - - -fi - - for ac_func in \ - ERR_load_KDF_strings \ EVP_PBE_scrypt \ - SSL_CIPHER_find \ - SSL_CTX_set1_groups_list \ SSL_CTX_set_security_level \ - SSL_SESSION_get_master_key \ - SSL_get_client_ciphers \ - SSL_get_client_random \ - SSL_get_server_random \ - TLS_method \ + SSL_set_ciphersuites do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` @@ -11414,56 +11505,6 @@ done -ac_fn_c_check_member "$LINENO" "SSL" "state" "ac_cv_member_SSL_state" "#include - -" -if test "x$ac_cv_member_SSL_state" = xyes; then : - -cat >>confdefs.h <<_ACEOF -#define HAVE_SSL_STATE 1 -_ACEOF - - -fi - - -# The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of SHA_CTX" >&5 -$as_echo_n "checking size of SHA_CTX... " >&6; } -if ${ac_cv_sizeof_SHA_CTX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (SHA_CTX))" "ac_cv_sizeof_SHA_CTX" "$ac_includes_default -#include - -"; then : - -else - if test "$ac_cv_type_SHA_CTX" = yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (SHA_CTX) -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_sizeof_SHA_CTX=0 - fi -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_SHA_CTX" >&5 -$as_echo "$ac_cv_sizeof_SHA_CTX" >&6; } - - - -cat >>confdefs.h <<_ACEOF -#define SIZEOF_SHA_CTX $ac_cv_sizeof_SHA_CTX -_ACEOF - - - fi # enable_nss @@ -11598,6 +11639,8 @@ if test -d "$tor_trydir/lib"; then LDFLAGS="-L$tor_trydir/lib $LDFLAGS" + elif test -d "$tor_trydir/lib64"; then + LDFLAGS="-L$tor_trydir/lib64 $LDFLAGS" else LDFLAGS="-L$tor_trydir $LDFLAGS" fi @@ -11744,6 +11787,8 @@ if test -d "$tor_cv_library_zlib_dir/lib"; then LDFLAGS="-L$tor_cv_library_zlib_dir/lib $LDFLAGS" + elif test -d "$tor_cv_library_zlib_dir/lib64"; then + LDFLAGS="-L$tor_cv_library_zlib_dir/lib64 $LDFLAGS" else LDFLAGS="-L$tor_cv_library_zlib_dir $LDFLAGS" fi @@ -11763,6 +11808,9 @@ if test -d "$tor_cv_library_zlib_dir/lib"; then TOR_LDFLAGS_zlib="-L$tor_cv_library_zlib_dir/lib" TOR_LIBDIR_zlib="$tor_cv_library_zlib_dir/lib" + elif test -d "$tor_cv_library_zlib_dir/lib64"; then + TOR_LDFLAGS_zlib="-L$tor_cv_library_zlib_dir/lib64" + TOR_LIBDIR_zlib="$tor_cv_library_zlib_dir/lib64" else TOR_LDFLAGS_zlib="-L$tor_cv_library_zlib_dir" TOR_LIBDIR_zlib="$tor_cv_library_zlib_dir" @@ -13455,6 +13503,141 @@ +# From https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html: +# +# Enable code instrumentation to increase program security by checking that +# target addresses of control-flow transfer instructions are valid. This +# prevents diverting the flow of control to an unexpected target. This is +# intended to protect against such threats as Return-oriented Programming +# (ROP), and similarly call/jmp-oriented programming (COP/JOP). + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler accepts -fcf-protection=full" >&5 +$as_echo_n "checking whether the compiler accepts -fcf-protection=full... " >&6; } +if ${tor_cv_cflags__fcf_protection_full+:} false; then : + $as_echo_n "(cached) " >&6 +else + + tor_saved_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -pedantic -Werror -fcf-protection=full" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tor_cv_cflags__fcf_protection_full=yes +else + tor_cv_cflags__fcf_protection_full=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test x != x; then + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tor_can_link__fcf_protection_full=yes +else + tor_can_link__fcf_protection_full=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + fi + CFLAGS="$tor_saved_CFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tor_cv_cflags__fcf_protection_full" >&5 +$as_echo "$tor_cv_cflags__fcf_protection_full" >&6; } + if test x$tor_cv_cflags__fcf_protection_full = xyes; then + CFLAGS="$CFLAGS -fcf-protection=full" + else + true + fi + + + +# The equivalent for arm64 (#41139) + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler accepts -mbranch-protection=standard" >&5 +$as_echo_n "checking whether the compiler accepts -mbranch-protection=standard... " >&6; } +if ${tor_cv_cflags__mbranch_protection_standard+:} false; then : + $as_echo_n "(cached) " >&6 +else + + tor_saved_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -pedantic -Werror -mbranch-protection=standard" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tor_cv_cflags__mbranch_protection_standard=yes +else + tor_cv_cflags__mbranch_protection_standard=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test x != x; then + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + tor_can_link__mbranch_protection_standard=yes +else + tor_can_link__mbranch_protection_standard=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + fi + CFLAGS="$tor_saved_CFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tor_cv_cflags__mbranch_protection_standard" >&5 +$as_echo "$tor_cv_cflags__mbranch_protection_standard" >&6; } + if test x$tor_cv_cflags__mbranch_protection_standard = xyes; then + CFLAGS="$CFLAGS -mbranch-protection=standard" + else + true + fi + + + + if test "x$enable_seccomp" != "xno"; then for ac_header in seccomp.h @@ -28823,8 +29006,8 @@ - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wextra-semi" >&5 -$as_echo_n "checking whether C compiler accepts -Wextra-semi... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler accepts -Wextra-semi" >&5 +$as_echo_n "checking whether the C compiler accepts -Wextra-semi... " >&6; } if ${ax_cv_check_cflags__Werror__Wextra_semi+:} false; then : $as_echo_n "(cached) " >&6 else @@ -29706,7 +29889,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by tor $as_me 0.4.8.16, which was +This file was extended by tor $as_me 0.4.9.6, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -29772,7 +29955,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -tor config.status 0.4.8.16 +tor config.status 0.4.9.6 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru tor-0.4.8.16/configure.ac tor-0.4.9.6/configure.ac --- tor-0.4.8.16/configure.ac 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/configure.ac 2026-03-25 14:30:34.000000000 +0000 @@ -4,7 +4,7 @@ dnl See LICENSE for licensing information AC_PREREQ([2.63]) -AC_INIT([tor],[0.4.8.16]) +AC_INIT([tor],[0.4.9.6]) AC_CONFIG_SRCDIR([src/app/main/tor_main.c]) AC_CONFIG_MACRO_DIR([m4]) @@ -18,7 +18,7 @@ # version number changes. Tor uses it to make sure that it # only shuts down for missing "required protocols" when those protocols # are listed as required by a consensus after this date. -AC_DEFINE(APPROX_RELEASE_DATE, ["2025-03-24"], # for 0.4.8.16 +AC_DEFINE(APPROX_RELEASE_DATE, ["2026-03-25"], # for 0.4.9.6 [Approximate date when this software was released. (Updated when the version changes.)]) # "foreign" means we don't follow GNU package layout standards @@ -570,6 +570,21 @@ AC_DEFINE(HAVE_ATTR_FALLTHROUGH, [1], [defined if we have the fallthrough attribute.]) fi +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -Werror" +AC_CACHE_CHECK([for __attribute__((nonstring))], + tor_cv_c_attr_nonstring, + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([], + [[ __attribute__((nonstring)) const char foo[5] = "abcde"; ]])], + [tor_cv_c_attr_nonstring=yes], + [tor_cv_c_attr_nonstring=no] )]) +CFLAGS="$saved_CFLAGS" + +if test "$tor_cv_c_attr_nonstring" = "yes"; then + AC_DEFINE(HAVE_ATTR_NONSTRING, [1], [defined if we have the nonstring attribute.]) +fi + TORUSER=_tor AC_ARG_WITH(tor-user, AS_HELP_STRING(--with-tor-user=NAME, [specify username for tor daemon]), @@ -979,6 +994,23 @@ [have_nss=no; AC_MSG_ERROR([You asked for NSS but I can't find it, $pkg_config_user_action, or set NSS_CFLAGS and NSS_LIBS.])]) AC_SUBST(NSS_CFLAGS) AC_SUBST(NSS_LIBS) + + save_CFLAGS="$CFLAGS" + save_LIBS="$LIBS" + LIBS="$LIBS $NSS_LIBS" + CFLAGS="$CFLAGS $NSS_CFLAGS" + AC_MSG_CHECKING([whether NSS defines ssl_kea_ecdh_hybrid(_psk)]) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ + #include + int v = (int) ssl_kea_ecdh_hybrid_psk; + int v2 = (int) ssl_kea_ecdh_hybrid; + ]], [[]])], + [ AC_MSG_RESULT([yes]); + AC_DEFINE(NSS_HAS_ECDH_HYBRID, 1, [whether nss defines ecdh_hybrid key exchange.]) + ], + [ AC_MSG_RESULT([no]) ]) + LIBS="$save_LIBS" + CPPFLAGS="$save_CPPFLAGS" fi dnl ------------------------------------------------------ @@ -1000,7 +1032,7 @@ fi ]) -AC_MSG_NOTICE([Now, we'll look for OpenSSL >= 1.0.1]) +AC_MSG_NOTICE([Now, we'll look for OpenSSL.]) TOR_SEARCH_LIBRARY(openssl, $tryssldir, [-lssl -lcrypto $TOR_LIB_GDI $TOR_LIB_WS32 $TOR_LIB_CRYPT32], [#include char *getenv(const char *);], @@ -1040,38 +1072,58 @@ dnl work. (See ticket tor#40166.) For now, we disable the deprecation dnl warnings. -AC_MSG_CHECKING([for OpenSSL >= 3.0.0]) +dnl --- Check for OpenSSL engine header --- +AC_CHECK_HEADERS([openssl/engine.h], [], + [AC_MSG_ERROR([Missing required header openssl/engine.h. + +On Debian/Ubuntu install: libssl-dev +On Fedora/RHEL install: openssl-devel-engine + +Then re-run configure.])]) + + +AC_MSG_CHECKING([for OpenSSL implementation]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include -#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L -#error "you_have_version_3" +#if defined(LIBRESSL_VERSION_NUMBER) +#error "this is libressl, no worries" #endif ]], [[]])], - [ AC_MSG_RESULT([no]) ], - [ AC_MSG_RESULT([yes]); - AC_DEFINE(OPENSSL_SUPPRESS_DEPRECATED, 1, [disable openssl deprecated-function warnings]) ]) + [ openssl_impl=openssl + AC_MSG_RESULT([OpenSSL]) + AC_DEFINE(OPENSSL_SUPPRESS_DEPRECATED, 1, [disable openssl deprecated-function warnings]) + ], + [ openssl_impl=libressl + AC_MSG_RESULT([LibreSSL]) + ]) -AC_MSG_CHECKING([for OpenSSL < 1.0.1]) +if test "x$openssl_impl" = "xopenssl"; then +AC_MSG_CHECKING([for OpenSSL < 1.1.1]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include -#if OPENSSL_VERSION_NUMBER < 0x1000100fL -#error "too old" +#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10101000L +#error "openssl too old" #endif ]], [[]])], [ AC_MSG_RESULT([no]) ], - [ AC_MSG_ERROR([OpenSSL is too old. We require 1.0.1 or later. You can specify a path to a newer one with --with-openssl-dir.]) ]) + [ AC_MSG_RESULT([yes]) + AC_MSG_ERROR([Your version of OpenSSL is too old. We require 1.1.1 or later, and you should use 3.5 if possible.]) + ]) +fi -AC_MSG_CHECKING([whether LibreSSL TLS 1.3 APIs are busted]) +if test "x$openssl_impl" = "xlibressl"; then +AC_MSG_CHECKING([for LibreSSL < 3.7.0]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include -#if defined(LIBRESSL_VERSION_NUMBER) && \ - LIBRESSL_VERSION_NUMBER >= 0x3020100fL && \ - LIBRESSL_VERSION_NUMBER < 0x3040100fL -#error "oh no" +#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3070000fL +#error "libressl too old" #endif ]], [[]])], [ AC_MSG_RESULT([no]) ], - [ AC_MSG_ERROR([This version of LibreSSL won't work with Tor. Please upgrade to LibreSSL 3.4.1 or later. (Or downgrade to 3.2.0 if you really must.)]) ]) + [ AC_MSG_RESULT([yes]) + AC_MSG_ERROR([Your version of LibreSSL is too old. We require 3.7.0 or later.]) + ]) +fi AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include @@ -1108,34 +1160,14 @@ fi], [openssl_ver_mismatch=cross]) AC_MSG_RESULT([$openssl_ver_mismatch]) -AC_CHECK_MEMBERS([struct ssl_method_st.get_cipher_by_char], , , -[#include -]) - dnl OpenSSL functions which we might not have. In theory, we could just dnl check the openssl version number, but in practice that gets pretty dnl confusing with LibreSSL, OpenSSL, and various distributions' patches dnl to them. AC_CHECK_FUNCS([ \ - ERR_load_KDF_strings \ EVP_PBE_scrypt \ - SSL_CIPHER_find \ - SSL_CTX_set1_groups_list \ SSL_CTX_set_security_level \ - SSL_SESSION_get_master_key \ - SSL_get_client_ciphers \ - SSL_get_client_random \ - SSL_get_server_random \ - TLS_method \ - ]) - -dnl Check if OpenSSL structures are opaque -AC_CHECK_MEMBERS([SSL.state], , , -[#include -]) - -AC_CHECK_SIZEOF(SHA_CTX, , [AC_INCLUDES_DEFAULT() -#include + SSL_set_ciphersuites ]) fi # enable_nss @@ -1474,6 +1506,17 @@ dnl code will work. TOR_CHECK_CFLAGS(-fasynchronous-unwind-tables) +# From https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html: +# +# Enable code instrumentation to increase program security by checking that +# target addresses of control-flow transfer instructions are valid. This +# prevents diverting the flow of control to an unexpected target. This is +# intended to protect against such threats as Return-oriented Programming +# (ROP), and similarly call/jmp-oriented programming (COP/JOP). +TOR_CHECK_CFLAGS(-fcf-protection=full) +# The equivalent for arm64 (#41139) +TOR_CHECK_CFLAGS(-mbranch-protection=standard) + dnl ============================================================ dnl Check for libseccomp diff -Nru tor-0.4.8.16/contrib/win32build/tor-mingw.nsi.in tor-0.4.9.6/contrib/win32build/tor-mingw.nsi.in --- tor-0.4.8.16/contrib/win32build/tor-mingw.nsi.in 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/contrib/win32build/tor-mingw.nsi.in 2026-03-25 14:30:34.000000000 +0000 @@ -8,7 +8,7 @@ !include "LogicLib.nsh" !include "FileFunc.nsh" !insertmacro GetParameters -!define VERSION "0.4.8.16" +!define VERSION "0.4.9.6" !define INSTALLER "tor-${VERSION}-win32.exe" !define WEBSITE "https://www.torproject.org/" !define LICENSE "LICENSE" diff -Nru tor-0.4.8.16/debian/.debian-ci.yml tor-0.4.9.6/debian/.debian-ci.yml --- tor-0.4.8.16/debian/.debian-ci.yml 2026-04-05 21:20:33.000000000 +0000 +++ tor-0.4.9.6/debian/.debian-ci.yml 2026-04-05 21:20:34.000000000 +0000 @@ -50,7 +50,7 @@ - rm -rf build-env - *apt-init - apt-get install sudo - - apt-get install build-essential + - apt-get install adduser build-essential - apt-get install $(cat debian/.debian-ci/"${CI_JOB_NAME}"/build-depends) - adduser --system --group --disabled-password --shell /bin/sh --home "$CI_PROJECT_DIR"/build-env "${BUILDUSER}" artifacts: @@ -68,7 +68,7 @@ - rm -rf build-env binary-packages - *apt-init - apt-get install sudo - - apt-get install build-essential devscripts reprepro fakeroot + - apt-get install adduser build-essential devscripts reprepro fakeroot #image: ${DOCKER_ARCH}/${OS}:${SUITE}${IMAGE_EXTENSION} image: containers.torproject.org/tpo/tpa/base-images/${OS}:${SUITE} retry: @@ -150,29 +150,25 @@ .matrix_full: &matrix_full - OS: debian - SUITE: [ 'sid', 'bullseye', 'bookworm', 'trixie' ] + SUITE: [ 'sid', 'bookworm', 'trixie', 'forky' ] DOCKER_ARCH: amd64 HOSTING_PROVIDER_TAG: tpa - OS: debian - SUITE: [ 'sid', 'bullseye', 'bookworm', 'trixie' ] + SUITE: [ 'sid', 'bookworm', 'trixie', 'forky' ] DOCKER_ARCH: arm64 HOSTING_PROVIDER_TAG: osuosl - OS: debian - SUITE: 'bullseye' - DOCKER_ARCH: amd64 - HOSTING_PROVIDER_TAG: tpa - - OS: debian SUITE: 'bookworm' DOCKER_ARCH: amd64 HOSTING_PROVIDER_TAG: tpa SPECIAL: [ 'bpo12' ] - OS: ubuntu - SUITE: [ 'focal', 'jammy', 'noble', 'oracular' ] + SUITE: [ 'jammy', 'noble', 'plucky', 'questing' ] DOCKER_ARCH: amd64 HOSTING_PROVIDER_TAG: tpa - OS: ubuntu - SUITE: [ 'focal', 'jammy', 'noble', 'oracular' ] + SUITE: [ 'jammy', 'noble', 'plucky', 'questing' ] DOCKER_ARCH: arm64 HOSTING_PROVIDER_TAG: osuosl @@ -291,4 +287,4 @@ paths: - binary-packages - source-packages - expire_in: 1 month + expire_in: 6 months diff -Nru tor-0.4.8.16/debian/changelog tor-0.4.9.6/debian/changelog --- tor-0.4.8.16/debian/changelog 2026-04-05 21:20:33.000000000 +0000 +++ tor-0.4.9.6/debian/changelog 2026-04-05 21:20:34.000000000 +0000 @@ -1,3 +1,70 @@ +tor (0.4.9.6-0+deb13u1) trixie-security; urgency=medium + + * Upload 0.4.9.x tree to debian-security: Fixes, among other things: + - TROVE-2026-004 (memory compare using the wrong length) + - TROVE-2025-016 (out-of-bounds read error with V1 EXTEND cells) + + -- Peter Palfrader Sun, 05 Apr 2026 09:31:58 +0200 + +tor (0.4.9.6-1) unstable; urgency=medium + + * New upstream version. + * Drop 64b5638b backport patch + + -- Jérôme Charaoui Wed, 25 Mar 2026 14:55:12 -0400 + +tor (0.4.9.5-2) unstable; urgency=medium + + * Include 64b5638b from + https://gitlab.torproject.org/tpo/core/tor/-/merge_requests/990 + to fix issues on big-endian systems (closes: #1128946) + * tests/setup-onion-service: include onionshare -> onionshare-cli dependency + change from the debian-main branch, also dropping the unzip dependency. + + -- Peter Palfrader Thu, 26 Feb 2026 12:29:42 +0100 + +tor (0.4.9.5-1) unstable; urgency=medium + + * New upsteam tree. + + -- Jérôme Charaoui Thu, 12 Feb 2026 13:11:02 -0500 + +tor (0.4.8.22-1) unstable; urgency=medium + + * New upstream version. + + -- Jérôme Charaoui Wed, 28 Jan 2026 14:36:16 -0500 + +tor (0.4.8.21-1) unstable; urgency=medium + + * New upstream version. + + -- Jérôme Charaoui Mon, 17 Nov 2025 15:05:05 -0500 + +tor (0.4.8.20-1) unstable; urgency=medium + + * New upstream version. + + -- Jérôme Charaoui Mon, 10 Nov 2025 15:37:11 -0500 + +tor (0.4.8.19-1) unstable; urgency=medium + + * New upstream version. + + -- Gabriel Filion Thu, 09 Oct 2025 16:31:29 -0400 + +tor (0.4.8.18-1) unstable; urgency=medium + + * New upstream version. + + -- Jérôme Charaoui Tue, 16 Sep 2025 13:05:13 -0400 + +tor (0.4.8.17-1) unstable; urgency=medium + + * New upstream version. + + -- Gabriel Filion Thu, 17 Jul 2025 15:37:06 -0400 + tor (0.4.8.16-1) unstable; urgency=medium * New upstream version. diff -Nru tor-0.4.8.16/debian/micro-revision.i tor-0.4.9.6/debian/micro-revision.i --- tor-0.4.8.16/debian/micro-revision.i 2026-04-05 21:20:33.000000000 +0000 +++ tor-0.4.9.6/debian/micro-revision.i 2026-04-05 21:20:34.000000000 +0000 @@ -1 +1 @@ -"0d7c17a48a27e0c3" +"67d83a6b7dd2a191" diff -Nru tor-0.4.8.16/debian/misc/backport tor-0.4.9.6/debian/misc/backport --- tor-0.4.8.16/debian/misc/backport 2026-04-05 21:20:33.000000000 +0000 +++ tor-0.4.9.6/debian/misc/backport 2026-04-05 21:20:34.000000000 +0000 @@ -41,6 +41,7 @@ bullseye d11.bullseye 1 bookworm d12.bookworm 1 trixie d13.trixie 1 +forky d14.forky 1 lenny-bpo bpo5 1 lenny-backports squeeze-bpo bpo6 1 squeeze-backports @@ -51,6 +52,7 @@ bullseye-bpo bpo11 1 bullseye-backports bookworm-bpo bpo12 1 bookworm-backports trixie-bpo bpo13 1 trixie-backports +forky-bpo bpo14 1 forky-backports dapper dapper 1 edgy edgy 1 @@ -90,6 +92,8 @@ mantic mantic 1 noble noble 1 oracular oracular 1 +plucky plucky 1 +questing questing 1 EOF ) if [ -z "$result" ] ; then diff -Nru tor-0.4.8.16/debian/misc/build-tor-sources tor-0.4.9.6/debian/misc/build-tor-sources --- tor-0.4.8.16/debian/misc/build-tor-sources 2026-04-05 21:20:33.000000000 +0000 +++ tor-0.4.9.6/debian/misc/build-tor-sources 2026-04-05 21:20:34.000000000 +0000 @@ -33,315 +33,326 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -assert_files_dont_exist () { - local pkg="$1"; shift - local debian_version="$1"; - if [ -z "$debian_version" ]; then - echo "assert_files_dont_exist called without debian_version" >&2 - exit 1; - fi - - if [ -e "${pkg}_$debian_version.diff.gz" ] ; then - echo "${pkg}_$debian_version.diff.gz already exists" >&2 - exit 1; - fi - if [ -e "${pkg}_$debian_version.dsc" ] ; then - echo "${pkg}_$debian_version.dsc already exists" >&2 - exit 1; - fi - if [ -e "${pkg}_$debian_version""_amd64.deb" ] ; then - echo "${pkg}_$debian_version""_amd64.deb already exists" >&2 - exit 1; - fi - if [ -e "${pkg}_$debian_version""_amd64.changes" ] ; then - echo "${pkg}_$debian_version""_amd64.changes already exists" >&2 - exit 1; - fi +assert_files_dont_exist() { + local pkg="$1" + shift + local debian_version="$1" + if [ -z "$debian_version" ]; then + echo "assert_files_dont_exist called without debian_version" >&2 + exit 1 + fi + + if [ -e "${pkg}_$debian_version.diff.gz" ]; then + echo "${pkg}_$debian_version.diff.gz already exists" >&2 + exit 1 + fi + if [ -e "${pkg}_$debian_version.dsc" ]; then + echo "${pkg}_$debian_version.dsc already exists" >&2 + exit 1 + fi + if [ -e "${pkg}_$debian_version""_amd64.deb" ]; then + echo "${pkg}_$debian_version""_amd64.deb already exists" >&2 + exit 1 + fi + if [ -e "${pkg}_$debian_version""_amd64.changes" ]; then + echo "${pkg}_$debian_version""_amd64.changes already exists" >&2 + exit 1 + fi } get_debian_version() { - local dir="$1"; shift - local which="${1:-}"; shift - - if [ -z "$which" ]; then - ( cd $dir && dpkg-parsechangelog | grep-dctrl -n -s Version '' ) - else - local v=$(get_debian_version $dir) - case "$which" in - upstream) echo "${v%-*}" ;; - debrev) echo "${v##*-}" ;; - *) - echo >&2 "Unknown key '$which' in get_debian_version" - exit 1 - esac - fi + local dir="$1" + shift + local which="${1:-}" + shift + + if [ -z "$which" ]; then + (cd $dir && dpkg-parsechangelog | grep-dctrl -n -s Version '') + else + local v=$(get_debian_version $dir) + case "$which" in + upstream) echo "${v%-*}" ;; + debrev) echo "${v##*-}" ;; + *) + echo >&2 "Unknown key '$which' in get_debian_version" + exit 1 + ;; + esac + fi } # remove_completely ... 0 replace hardening-includes with hardening-wrapper # 1 get rid entirely hardening_backport() { - local remove_completely="$1" + local remove_completely="$1" - sed -i -e '/^Build-Depends/ s/, *hardening-includes//' debian/control - if [ "$remove_completely" = 0 ]; then - sed -i -e '/^Build-Depends/ s/$/, hardening-wrapper/' debian/control - fi - - if [ "$remove_completely" = 0 ]; then - sed -i -e 's#include /usr/share/hardening-includes/hardening.make#export DEB_BUILD_HARDENING=1#' debian/rules - sed -i -e '/export DEB_BUILD_HARDENING=1/ a export DEB_BUILD_HARDENING_DEBUG=1' debian/rules - else - sed -i -e 's#include /usr/share/hardening-includes/hardening.make##' debian/rules - fi - - if [ "$remove_completely" = 0 ]; then - dch --append "Replace hardening-includes use with hardening-wrapper." - else - dch --append "Completely remove hardening-includes use." - fi + sed -i -e '/^Build-Depends/ s/, *hardening-includes//' debian/control + if [ "$remove_completely" = 0 ]; then + sed -i -e '/^Build-Depends/ s/$/, hardening-wrapper/' debian/control + fi + + if [ "$remove_completely" = 0 ]; then + sed -i -e 's#include /usr/share/hardening-includes/hardening.make#export DEB_BUILD_HARDENING=1#' debian/rules + sed -i -e '/export DEB_BUILD_HARDENING=1/ a export DEB_BUILD_HARDENING_DEBUG=1' debian/rules + else + sed -i -e 's#include /usr/share/hardening-includes/hardening.make##' debian/rules + fi + + if [ "$remove_completely" = 0 ]; then + dch --append "Replace hardening-includes use with hardening-wrapper." + else + dch --append "Completely remove hardening-includes use." + fi } remove_runit() { - if grep -q dh-runit debian/control; then - sed -i -e '/^Build-Depends/ s/, *dh-runit\([^,]*\)\?//' debian/control - dch --append "Remove dh-runit build dependency and --with-runit for backport." - fi - sed -i -e "s/--with[[:space:]]*runit//" debian/rules + if grep -q dh-runit debian/control; then + sed -i -e '/^Build-Depends/ s/, *dh-runit\([^,]*\)\?//' debian/control + dch --append "Remove dh-runit build dependency and --with-runit for backport." + fi + sed -i -e "s/--with[[:space:]]*runit//" debian/rules } old_dh_systemd() { - dch --append "Restore build-dependency on dh-systemd and lower debhelper version requirement to 9.20160114" - sed -i -e '/^Build-Depends/ s/debhelper [^,]*, */debhelper (>= 9.20160114), dh-systemd [linux-any], /' debian/control + dch --append "Restore build-dependency on dh-systemd and lower debhelper version requirement to 9.20160114" + sed -i -e '/^Build-Depends/ s/debhelper [^,]*, */debhelper (>= 9.20160114), dh-systemd [linux-any], /' debian/control } systemd_in_lib() { - dch --append "Keep systemd files in /lib (as opposed to /usr/lib)" - sed -i -e 's,usr/lib/systemd,lib/systemd,' debian/tor.install debian/tor.dirs + dch --append "Keep systemd files in /lib (as opposed to /usr/lib)" + sed -i -e 's,usr/lib/systemd,lib/systemd,' debian/tor.install debian/tor.dirs } - bp1() { - local pkg="$1"; shift - local dir="$1"; shift - local sid_debian_version="$1"; shift - local dist="$1"; shift - - dpkg-source -x ${pkg}_$sid_debian_version.dsc - (cd $dir; backport $dist) + local pkg="$1" + shift + local dir="$1" + shift + local sid_debian_version="$1" + shift + local dist="$1" + shift + + dpkg-source -x ${pkg}_$sid_debian_version.dsc + ( + cd $dir + backport $dist + ) } bp2() { - local pkg="$1"; shift - local dir="$1"; shift - local origtar="$1"; shift - - local debian_version=$(get_debian_version $dir) - assert_files_dont_exist $pkg $debian_version - dpkg-source -b $dir $origtar - rm -r $dir + local pkg="$1" + shift + local dir="$1" + shift + local origtar="$1" + shift + + local debian_version=$(get_debian_version $dir) + assert_files_dont_exist $pkg $debian_version + dpkg-source -b $dir $origtar + rm -r $dir } backport_all() { - local pkg="$1"; shift - local dir="$1"; shift - local origtar="$1"; shift - local sid_debian_version="$1"; shift - - # sid - ################################################# - # null - -# # buster -# ################################################# -# bp1 $pkg $dir $sid_debian_version buster -# (cd $dir; systemd_in_lib) -# (cd $dir; remove_runit) -# bp2 $pkg $dir $origtar - - # bullseye - ################################################# - bp1 $pkg $dir $sid_debian_version bullseye - (cd $dir; systemd_in_lib) - bp2 $pkg $dir $origtar - - # bookworm - ################################################# - bp1 $pkg $dir $sid_debian_version bookworm - (cd $dir; systemd_in_lib) - bp2 $pkg $dir $origtar - - # trixie - ################################################# - bp1 $pkg $dir $sid_debian_version trixie - bp2 $pkg $dir $origtar - - - # focal (EOL: 2025-04, 2030-04) - ################################################# - bp1 $pkg $dir $sid_debian_version focal - (cd $dir; systemd_in_lib) - bp2 $pkg $dir $origtar - - # jammy (EOL: 2027-04-21, 2032-04) - ################################################# - bp1 $pkg $dir $sid_debian_version jammy - (cd $dir; systemd_in_lib) - bp2 $pkg $dir $origtar - - # noble (EOL: 2036-04) - ################################################# - bp1 $pkg $dir $sid_debian_version noble - bp2 $pkg $dir $origtar - - # oracular (EOL: 2025-07) - ################################################# - bp1 $pkg $dir $sid_debian_version oracular - bp2 $pkg $dir $origtar - - ################################################# - ## BPO - ################################################# - - # Backport to bookworm(debian 12) backports - dpkg-source -x ${pkg}_$sid_debian_version.dsc - ( - cd $dir - dch --bpo '' - systemd_in_lib - head debian/changelog - ) - bp2 $pkg $dir $origtar - - # Backport to bullseye(debian 11) sloppy backports - dpkg-source -x ${pkg}_$sid_debian_version.dsc - ( - cd $dir - dch --bpo '' - systemd_in_lib - head debian/changelog - sed -i -e '1,3s/bookworm-backports/bullseye-backports-sloppy/' debian/changelog - sed -i -e '1s/bpo12/bpo11/' debian/changelog - ) - bp2 $pkg $dir $origtar + local pkg="$1" + shift + local dir="$1" + shift + local origtar="$1" + shift + local sid_debian_version="$1" + shift + + # sid + ################################################# + # null + + # bookworm + ################################################# + bp1 $pkg $dir $sid_debian_version bookworm + ( + cd $dir + systemd_in_lib + ) + bp2 $pkg $dir $origtar + + # trixie + ################################################# + bp1 $pkg $dir $sid_debian_version trixie + bp2 $pkg $dir $origtar + + # forky + ################################################# + bp1 $pkg $dir $sid_debian_version forky + bp2 $pkg $dir $origtar + + # jammy (EOL: 2027-04-21, 2032-04) + ################################################# + bp1 $pkg $dir $sid_debian_version jammy + ( + cd $dir + systemd_in_lib + ) + bp2 $pkg $dir $origtar + + # noble (EOL: 2036-04) + ################################################# + bp1 $pkg $dir $sid_debian_version noble + bp2 $pkg $dir $origtar + + # plucky (EOL: 2026-01) + ################################################# + bp1 $pkg $dir $sid_debian_version plucky + bp2 $pkg $dir $origtar + + # questing (EOL: 2026-07) + ################################################# + bp1 $pkg $dir $sid_debian_version questing + bp2 $pkg $dir $origtar + + ################################################# + ## BPO + ################################################# + + # Backport to trixie(debian 13) backports + dpkg-source -x ${pkg}_$sid_debian_version.dsc + ( + cd $dir + dch --bpo '' + head debian/changelog + ) + bp2 $pkg $dir $origtar + + # Backport to bookworm(debian 12) sloppy backports + dpkg-source -x ${pkg}_$sid_debian_version.dsc + ( + cd $dir + dch --bpo '' + systemd_in_lib + head debian/changelog + sed -i -e '1,3s/trixie-backports/bookworm-backports-sloppy/' debian/changelog + sed -i -e '1s/bpo13/bpo12/' debian/changelog + ) + bp2 $pkg $dir $origtar } main() { - local origtar="$1"; shift - local deb_revision="$1"; shift - local gitdir="$1"; shift - local pkg="$1"; shift - - [ -d local-build ] || mkdir local-build - - if [ -z "$origtar" ] ; then - echo "Usage: $0 [debian-revision]" >&2 - exit 1; - fi - - - if [ ! -e "$origtar" ] ; then - echo "$origtar does not exist." >&2 - exit 1; - fi - - if [ "${origtar#${pkg}-}" != $origtar ]; then - ver="$origtar" - ver=${ver#${pkg}-} - ver=${ver%.tar.gz} - neworig="${pkg}_$ver.orig.tar.gz" - if ! [ -e "$neworig" ]; then - ln -v "$origtar" "$neworig" - fi - echo "Using $neworig instead of $origtar" - origtar="$neworig" - fi - - local dir - local dir_version - dir=`tar tzf $origtar 2>/dev/null | head -n1` - dir="${dir%%/}" - dir_version="${dir##${pkg}-}" - if [ -e "$dir" ] ; then - echo "$dir already exists." >&2 - exit 1; - fi - tar xzf $origtar - git clone -n -s "$gitdir" git-"$dir" - local tag="debian-${pkg}-$dir_version-${deb_revision//\~/_}" - (cd "git-$dir" && git checkout $tag) - if diff -qr "git-$dir" "$dir" --exclude .git | grep -v '^Only in ' | grep --color .; then - echo "Differenced detected." - exit 1 - fi - (cd "git-$dir" && echo "\"`git rev-parse --short=16 "$tag"`\"" > "debian/micro-revision.i") - cp -av "git-$dir/debian" "$dir" - rm -rf "git-$dir" - - - debian_upstream_version=$(get_debian_version $dir upstream) - if [ "$origtar" != "${pkg}_$debian_upstream_version.orig.tar.gz" ] ; then - echo "possible mismatch: $origtar but $debian_upstream_version in debian/changelog" >&2 - exit 1; - fi - - debian_version=$(get_debian_version $dir) - sid_debian_version="$debian_version" - assert_files_dont_exist $pkg $debian_version - dpkg-source -b $dir $origtar - rm -r $dir - - - - # local - ################################################# - cd local-build - dpkg-source -x ../${pkg}_$debian_version.dsc - cd ${pkg}-$debian_upstream_version - debuild -j8 -rfakeroot -uc -us - cd ../.. - + local origtar="$1" + shift + local deb_revision="$1" + shift + local gitdir="$1" + shift + local pkg="$1" + shift + + [ -d local-build ] || mkdir local-build + + if [ -z "$origtar" ]; then + echo "Usage: $0 [debian-revision]" >&2 + exit 1 + fi + + if [ ! -e "$origtar" ]; then + echo "$origtar does not exist." >&2 + exit 1 + fi + + if [ "${origtar#${pkg}-}" != $origtar ]; then + ver="$origtar" + ver=${ver#${pkg}-} + ver=${ver%.tar.gz} + neworig="${pkg}_$ver.orig.tar.gz" + if ! [ -e "$neworig" ]; then + ln -v "$origtar" "$neworig" + fi + echo "Using $neworig instead of $origtar" + origtar="$neworig" + fi + + local dir + local dir_version + dir=$(tar tzf $origtar 2>/dev/null | head -n1) + dir="${dir%%/}" + dir_version="${dir##${pkg}-}" + if [ -e "$dir" ]; then + echo "$dir already exists." >&2 + exit 1 + fi + tar xzf $origtar + git clone -n -s "$gitdir" git-"$dir" + local tag="debian-${pkg}-$dir_version-${deb_revision//\~/_}" + (cd "git-$dir" && git checkout $tag) + if diff -qr "git-$dir" "$dir" --exclude .git | grep -v '^Only in ' | grep --color .; then + echo "Differenced detected." + exit 1 + fi + (cd "git-$dir" && echo "\"$(git rev-parse --short=16 "$tag")\"" >"debian/micro-revision.i") + cp -av "git-$dir/debian" "$dir" + rm -rf "git-$dir" + + debian_upstream_version=$(get_debian_version $dir upstream) + if [ "$origtar" != "${pkg}_$debian_upstream_version.orig.tar.gz" ]; then + echo "possible mismatch: $origtar but $debian_upstream_version in debian/changelog" >&2 + exit 1 + fi + + debian_version=$(get_debian_version $dir) + sid_debian_version="$debian_version" + assert_files_dont_exist $pkg $debian_version + dpkg-source -b $dir $origtar + rm -r $dir + + # local + ################################################# + cd local-build + dpkg-source -x ../${pkg}_$debian_version.dsc + cd ${pkg}-$debian_upstream_version + debuild -j8 -rfakeroot -uc -us + cd ../.. - [ "$DO_BACKPORTS" -gt 0 ] && backport_all "$pkg" "$dir" "$origtar" "$sid_debian_version" + [ "$DO_BACKPORTS" -gt 0 ] && backport_all "$pkg" "$dir" "$origtar" "$sid_debian_version" - echo - echo "All done" + echo + echo "All done" } usage() { - cat << EOF + cat < EOF } # this is hardcoded to weasel's directory layout. sorry. case "$(basename $0)" in - build-tor-sources) - DO_BACKPORTS=1 - while getopts "hB" option; do - case "$option" in - h) - usage - exit - ;; - B) - DO_BACKPORTS=0 - ;; - *) - usage >&2 - exit 1 - ;; - esac - done - shift $(($OPTIND - 1)) - - set -e - set -x - GITDIR="${GITDIR:-$HOME/projects/tor/tor}" - if ! [ -e "$GITDIR/.git" ] ; then - echo >&2 "\$GITDIR does not exist or does not have a .git. It needs to point to the tor git repository." - exit 1 - fi - PKG="tor" - DO_BPO=1 - main "${1:-}" ${2:-1} $GITDIR $PKG - ;; +build-tor-sources) + DO_BACKPORTS=1 + while getopts "hB" option; do + case "$option" in + h) + usage + exit + ;; + B) + DO_BACKPORTS=0 + ;; + *) + usage >&2 + exit 1 + ;; + esac + done + shift $(($OPTIND - 1)) + + set -e + set -x + GITDIR="${GITDIR:-$HOME/projects/tor/tor}" + if ! [ -e "$GITDIR/.git" ]; then + echo >&2 "\$GITDIR does not exist or does not have a .git. It needs to point to the tor git repository." + exit 1 + fi + PKG="tor" + DO_BPO=1 + main "${1:-}" ${2:-1} $GITDIR $PKG + ;; esac diff -Nru tor-0.4.8.16/debian/tests/control tor-0.4.9.6/debian/tests/control --- tor-0.4.8.16/debian/tests/control 2026-04-05 21:20:33.000000000 +0000 +++ tor-0.4.9.6/debian/tests/control 2026-04-05 21:20:34.000000000 +0000 @@ -4,5 +4,5 @@ # Restrictions: isolation-container Tests: setup-onion-service -Depends: tor, netcat-openbsd, torsocks, curl, onionshare, colorized-logs, unzip, diffutils +Depends: tor, netcat-openbsd, torsocks, curl, onionshare-cli, colorized-logs, diffutils Restrictions: flaky diff -Nru tor-0.4.8.16/debian/tests/setup-onion-service tor-0.4.9.6/debian/tests/setup-onion-service --- tor-0.4.8.16/debian/tests/setup-onion-service 2026-04-05 21:20:33.000000000 +0000 +++ tor-0.4.9.6/debian/tests/setup-onion-service 2026-04-05 21:20:34.000000000 +0000 @@ -89,7 +89,7 @@ echo "================" fi echo "(Re-)Launching onionshare." - pipetty onionshare --debug data > "$ONIONSHARELOG" 2>&1 & + pipetty onionshare-cli --public --verbose data > "$ONIONSHARELOG" 2>&1 & onionsharepid="$!" fi } @@ -139,7 +139,7 @@ timeout=600 while [ "$timeout" -ge 0 ]; do - url=$(grep '^http.*\.onion/' "$ONIONSHARELOG" || true) + url=$(grep --only-matching 'http.*\.onion' "$ONIONSHARELOG" || true) [ -n "$url" ] && break sleep 1 launchshare @@ -156,7 +156,7 @@ --retry 5 \ --max-time 300 \ --location \ - -o data.zip \ + -o data.out \ --stderr - \ "$url/download" && rc=0 || rc=$? @@ -167,9 +167,7 @@ echo "Comparing file." -(mkdir unzip && cd unzip && unzip ../data.zip) - -if cmp data unzip/data; then +if cmp data data.out; then echo "Successfully downloaded file." exit 0 else diff -Nru tor-0.4.8.16/doc/asciidoc-helper.sh tor-0.4.9.6/doc/asciidoc-helper.sh --- tor-0.4.8.16/doc/asciidoc-helper.sh 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/doc/asciidoc-helper.sh 2026-03-25 14:30:34.000000000 +0000 @@ -12,8 +12,10 @@ exit 1 fi -SOURCE_DATE_EPOCH="$(git -C "$(dirname "$0")" show --no-patch --format='%ct')" -export SOURCE_DATE_EPOCH +if [ -z "$SOURCE_DATE_EPOCH" ]; then + SOURCE_DATE_EPOCH="$(git -C "$(dirname "$0")" show --no-patch --format='%ct')" + export SOURCE_DATE_EPOCH +fi output=$3 diff -Nru tor-0.4.8.16/doc/man/tor-gencert.1.in tor-0.4.9.6/doc/man/tor-gencert.1.in --- tor-0.4.8.16/doc/man/tor-gencert.1.in 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/doc/man/tor-gencert.1.in 2026-03-25 14:30:34.000000000 +0000 @@ -2,12 +2,12 @@ .\" Title: tor-gencert .\" Author: Tor Project, Inc. .\" Generator: DocBook XSL Stylesheets vsnapshot -.\" Date: 03/24/2025 +.\" Date: 03/25/2026 .\" Manual: Tor Manual .\" Source: Tor .\" Language: English .\" -.TH "TOR\-GENCERT" "1" "03/24/2025" "Tor" "Tor Manual" +.TH "TOR\-GENCERT" "1" "03/25/2026" "Tor" "Tor Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru tor-0.4.8.16/doc/man/tor-print-ed-signing-cert.1.in tor-0.4.9.6/doc/man/tor-print-ed-signing-cert.1.in --- tor-0.4.8.16/doc/man/tor-print-ed-signing-cert.1.in 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/doc/man/tor-print-ed-signing-cert.1.in 2026-03-25 14:30:34.000000000 +0000 @@ -2,12 +2,12 @@ .\" Title: tor-print-ed-signing-cert .\" Author: Tor Project, Inc. .\" Generator: DocBook XSL Stylesheets vsnapshot -.\" Date: 03/24/2025 +.\" Date: 03/25/2026 .\" Manual: Tor Manual .\" Source: Tor .\" Language: English .\" -.TH "TOR\-PRINT\-ED\-SIGN" "1" "03/24/2025" "Tor" "Tor Manual" +.TH "TOR\-PRINT\-ED\-SIGN" "1" "03/25/2026" "Tor" "Tor Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru tor-0.4.8.16/doc/man/tor-resolve.1.in tor-0.4.9.6/doc/man/tor-resolve.1.in --- tor-0.4.8.16/doc/man/tor-resolve.1.in 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/doc/man/tor-resolve.1.in 2026-03-25 14:30:34.000000000 +0000 @@ -2,12 +2,12 @@ .\" Title: tor-resolve .\" Author: Peter Palfrader .\" Generator: DocBook XSL Stylesheets vsnapshot -.\" Date: 03/24/2025 +.\" Date: 03/25/2026 .\" Manual: Tor Manual .\" Source: Tor .\" Language: English .\" -.TH "TOR\-RESOLVE" "1" "03/24/2025" "Tor" "Tor Manual" +.TH "TOR\-RESOLVE" "1" "03/25/2026" "Tor" "Tor Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru tor-0.4.8.16/doc/man/tor.1.in tor-0.4.9.6/doc/man/tor.1.in --- tor-0.4.8.16/doc/man/tor.1.in 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/doc/man/tor.1.in 2026-03-25 14:30:34.000000000 +0000 @@ -2,12 +2,12 @@ .\" Title: tor .\" Author: [FIXME: author] [see http://www.docbook.org/tdg5/en/html/author] .\" Generator: DocBook XSL Stylesheets vsnapshot -.\" Date: 03/24/2025 +.\" Date: 03/25/2026 .\" Manual: Tor Manual .\" Source: Tor .\" Language: English .\" -.TH "TOR" "1" "03/24/2025" "Tor" "Tor Manual" +.TH "TOR" "1" "03/25/2026" "Tor" "Tor Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -220,6 +220,16 @@ directory of your Tor daemon, and make sure that they are owned by the user actually running the Tor daemon on your system\&. .RE .PP +\fB\-\-keygen\-family\fR \fIbasename\fR +.RS 4 +Generate a new family ID key in +\fIbasename\fR\&.secret_family_key\&. To use this key, install it on every relay in your family\&. (Put it in the relay\(cqs +KeyDirectory\&.) Also, store the corresponding family ID in +\fIbasename\fR\&.public_family_id\&. Then enable the corresponding FamilyID option on your relays\&. This command overwrites these files if they already exist\&. See +https://community\&.torproject\&.org/relay/setup/post\-install/family\-ids/ +for more information\&. +.RE +.PP \fB\-\-passphrase\-fd\fR \fIFILEDES\fR .RS 4 File descriptor to read the passphrase from\&. Note that unlike with the tor\-gencert program, the entire file contents are read and used as the passphrase, including any trailing newlines\&. If the file descriptor is not specified, the passphrase is read from the terminal by default\&. @@ -799,7 +809,7 @@ Tor can scrub potentially sensitive strings from log messages (e\&.g\&. addresses) by replacing them with the string [scrubbed]\&. This way logs can still be useful, but they don\(cqt leave behind personally identifying information about what sites a user might have visited\&. -If this option is set to 0, Tor will not perform any scrubbing, if it is set to 1, all potentially sensitive strings are replaced\&. If it is set to relay, all log messages generated when acting as a relay are sanitized, but all messages generated when acting as a client are not\&. Note: Tor may not heed this option when logging at log levels below Notice\&. (Default: 1) +If this option is set to 0, Tor will not perform any scrubbing, if it is set to 1, all potentially sensitive strings are replaced\&. If it is set to relay, all log messages generated when acting as a relay are sanitized, but all messages generated when acting as a client are not\&. Note: Tor may not heed this option when logging at log levels more verbose than Notice\&. (Default: 1) .RE .PP \fBSandbox\fR \fB0\fR|\fB1\fR @@ -901,7 +911,7 @@ .RS 4 .\} .nf -The only protocol supported right now \*(Aqhaproxy\*(Aq\&. This option is only for +The only protocol supported right now is \*(Aqhaproxy\*(Aq\&. This option is only for clients\&. (Default: none) + .fi .if n \{\ @@ -2293,6 +2303,14 @@ If ExitRelay is set to "auto", then Tor checks the ExitPolicy, ReducedExitPolicy, and IPv6Exit options\&. If at least one of these options is set, Tor behaves as if ExitRelay were set to 1\&. If none of these exit policy options are set, Tor behaves as if ExitRelay were set to 0\&. (Default: auto) .RE .PP +\fBReevaluateExitPolicy\fR \fB0\fR|\fB1\fR +.RS 4 +If set, reevaluate the exit policy on existing connections when reloading configuration\&. + + +When the exit policy of an exit node change while reloading configuration, connections made prior to this change could violate the new policy\&. By setting this to 1, Tor will check if such connections exist, and mark them for termination\&. (Default: 0) +.RE +.PP \fBExtendAllowPrivateAddresses\fR \fB0\fR|\fB1\fR .RS 4 When this option is enabled, Tor will connect to relays on localhost, RFC1918 addresses, and so on\&. In particular, Tor will make direct OR connections, and Tor routers allow EXTEND requests, to these private addresses\&. (Tor will always allow connections to bridges, proxies, and pluggable transports configured on private addresses\&.) Enabling this option can create security issues; you should probably leave it off\&. (Default: 0) @@ -2341,6 +2359,14 @@ message designed to help developers instrumenting Tor\(cqs main event loop\&. (Default: 0) .RE .PP +\fBMaxHSDirCacheBytes\fR \fIN\fR \fBbytes\fR|\fBKBytes\fR|\fBMBytes\fR|\fBGBytes\fR +.RS 4 +This option configures a threshold of Hidden Service Directory memory consumption above which your Tor relay will begin to prune the least\-frequently accessed hidden service descriptors from the relay\(cqs HSDir cache\&. If set to 0, this will default to 20% of MaxMemInQueues\&. (Default: 0) + + +This pruning used to be done as part of MaxMemInQueues, but it has been decoupled to allow more fine\-grained control of descriptor cache size under DDoS conditions\&. +.RE +.PP \fBMaxMemInQueues\fR \fIN\fR \fBbytes\fR|\fBKBytes\fR|\fBMBytes\fR|\fBGBytes\fR .RS 4 This option configures a threshold above which Tor will assume that it needs to stop queueing or buffering data because it\(cqs about to run out of memory\&. If it hits this threshold, it will begin killing circuits until it has recovered at least 10% of this memory\&. Do not set this option too low, or your relay may be unreliable under load\&. This option only affects some queues, so the actual process size will be larger than this\&. If this option is set to 0, Tor will try to pick a reasonable default based on your system\(cqs physical memory\&. (Default: 0) @@ -2364,6 +2390,29 @@ Note: do not use MyFamily when configuring your Tor instance as a bridge\&. .RE .PP +\fBFamilyId\fR \fIident\fR +.RS 4 +Configure this relay to be part of a family identified by a shared secret family key with the given key identity\&. A corresponding family key must be stored in the relay\(cqs key directory, with a filename ending with "\&.secret_family_key"\&. This option can appear multiple times\&. Family keys are generated with "\-\-keygen\-family"; this also generates the value you should use in the +\fIident\fR +field in a file ending with "\&.public_family_id"\&. For information on generating and installing a family key, see +https://community\&.torproject\&.org/relay/setup/post\-install/family\-ids/ + +In the future, this will be the preferred way for relays to advertise family membership\&. But for now, relay families should configure both this option +\fIand\fR +MyFamily, so older clients will still recognize the relays\*(Aq family membership\&. + +(Note that if the seccomp2 Sandbox feature is enabled, it is not possible to change the key filenames while Tor is running\&.) +.RE +.PP +\fBFamilyId\fR \fB * \fR +.RS 4 +Configure this relay to be part of +\fIevery\fR +family identified by any family ID key found in the family key directory\&. Only filenames ending with "\&.secret\e_family\e_key" are considered\&. Specifying family IDs in this way makes it unnecessary to adjust the configuration file if the family key is rotated, but it increases the likelihood of accidentally using a different set of family keys than the ones you had expected\&. +.RE +.sp +\fBFamilyKeyDirectory\fR \fIdirectory\fR: Configure a directory to use, in place of the key directory, when searching for family ID keys\&. +.PP \fBNickname\fR \fIname\fR .RS 4 Set the server\(cqs nickname to \*(Aqname\*(Aq\&. Nicknames must be between 1 and 19 characters inclusive, and must contain only the characters [a\-zA\-Z0\-9]\&. If not set, @@ -2902,6 +2951,36 @@ Refuse establishment of rendezvous points for single hop clients\&. In other words, if a client directly connects to the relay and sends an ESTABLISH_RENDEZVOUS cell, it is silently dropped\&. "auto" means use the consensus parameter\&. If not defined in the consensus, the value is 0\&. (Default: auto) .RE .sp +The following options are useful only for a exit relay\&. +.PP +\fBDoSStreamCreationEnabled\fR \fB0\fR|\fB1\fR|\fBauto\fR +.RS 4 +Enable the stream DoS mitigation\&. If set to 1 (enabled), tor will apply rate limit on the creation of new streams and dns requests per circuit\&. "auto" means use the consensus parameter\&. If not defined in the consensus, the value is 0\&. (Default: auto) +.RE +.PP +\fBDoSStreamCreationDefenseType\fR \fINUM\fR +.RS 4 +This is the type of defense applied to a detected circuit or stream for the stream mitigation\&. The possible values are: + +1: No defense\&. + +2: Reject the stream or resolve request\&. + +3: Close the circuit creating too many streams\&. + +"0" means use the consensus parameter\&. If not defined in the consensus, the value is 2\&. (Default: 0) +.RE +.PP +\fBDoSStreamCreationRate\fR \fINUM\fR +.RS 4 +The allowed rate of stream creation from a single circuit per second\&. Coupled with the burst (see below), if the limit is reached, actions can be taken against the stream or circuit (DoSStreamCreationDefenseType)\&. If not defined or set to 0, it is controlled by a consensus parameter\&. If not defined in the consensus, the value is 100\&. (Default: 0) +.RE +.PP +\fBDoSStreamCreationBurst\fR \fINUM\fR +.RS 4 +The allowed burst of stream creation from a circuit per second\&. See the DoSStreamCreationRate for more details on this detection\&. If not defined or set to 0, it is controlled by a consensus parameter\&. If not defined in the consensus, the value is 300\&. (Default: 0) +.RE +.sp For onion services, mitigations are a work in progress and multiple options are currently available\&. .sp The introduction point defense is a rate limit on the number of introduction requests that will be forwarded to a service by each of its honest introduction point routers\&. This can prevent some types of overwhelming floods from reaching the service, but it will also prevent legitimate clients from establishing new connections\&. @@ -2935,7 +3014,7 @@ .sp This might be too much for your use case or not, fine tuning these values is hard and are likely different for each service operator\&. .sp -Why is this not helping reachability of the service? Because the defenses are at the introduction point, an attacker can easily flood all introduction point rendering the service unavailable due to no client being able to pass through\&. But, the service itself is not overwhelmed with connetions allowing it to function properly for the few clients that were able to go through or other any services running on the same tor instance\&. +Why is this not helping reachability of the service? Because the defenses are at the introduction point, an attacker can easily flood all introduction point rendering the service unavailable due to no client being able to pass through\&. But, the service itself is not overwhelmed with connections allowing it to function properly for the few clients that were able to go through or other any services running on the same tor instance\&. .sp The bottom line is that this protects the network by preventing an onion service to flood the network with new rendezvous circuits that is reducing load on the network\&. .sp @@ -3108,7 +3187,7 @@ .PP \fBAuthDirRejectRequestsUnderLoad\fR \fB0\fR|\fB1\fR .RS 4 -If set, the directory authority will start rejecting directory requests from non relay connections by sending a 503 error code if it is under bandwidth pressure (reaching the configured limit if any)\&. Relays will always tried to be answered even if this is on\&. (Default: 1) +If set, the directory authority will start rejecting directory requests from non relay connections by sending a 503 error code if it is under bandwidth pressure (reaching the configured limit if any)\&. Relays will always be answered even if this is on\&. (Default: 1) .RE .sp \fBAuthDirBadExitCCs\fR \fICC\fR,\&... @@ -3224,6 +3303,11 @@ should be set too\&. .RE .PP +\fBMinimalAcceptedServerVersion\fR \fISTRING\fR +.RS 4 +STRING is the oldest Tor version accepted by the directory authority for relays and bridge\&. Any older version will be rejected\&. (Default: 0\&.4\&.7\&.0\-alpha\-dev) +.RE +.PP \fBV3AuthDistDelay\fR \fIN\fR \fBseconds\fR|\fBminutes\fR|\fBhours\fR .RS 4 V3 authoritative directories only\&. Configures the server\(cqs preferred delay between publishing its consensus and signature and assuming it has all the signatures from all the other authorities\&. Note that the actual time used is not the server\(cqs preferred time, but the consensus of all preferences\&. (Default: 5 minutes) @@ -4012,6 +4096,13 @@ file holds the previously generated key, which the relay uses to handle any requests that were made by clients that didn\(cqt have the new one\&. .RE .PP +\fIKeyDirectory\fR/\fIkeyname\fR\fB\&.secret_family_key\fR +.RS 4 +A relay family\(cqs family identity key\&. Used to prove membership in a relay family\&. See +https://community\&.torproject\&.org/relay/setup/post\-install/family\-ids/ +for more information\&. +.RE +.PP \fIDataDirectory\fR/\fBfingerprint\fR .RS 4 Only used by servers\&. Contains the fingerprint of the server\(cqs RSA identity key\&. @@ -4027,6 +4118,11 @@ Only used by bridges\&. Contains the hashed fingerprint of the bridge\(cqs identity key\&. (That is, the hash of the hash of the identity key\&.) .RE .PP +\fIDataDirectory\fR/\fBbridgelines\fR +.RS 4 +Only used by bridges\&. Contains the bridge lines that clients can use to connect using pluggable transports\&. +.RE +.PP \fIDataDirectory\fR/\fBapproved\-routers\fR .RS 4 Only used by authoritative directory servers\&. Each line lists a status and an identity, separated by whitespace\&. Identities can be hex\-encoded RSA fingerprints, or base\-64 encoded ed25519 public keys\&. See the @@ -4101,7 +4197,7 @@ Only used by servers\&. This file is used to collect approximate counts of what fraction of the traffic is hidden service rendezvous traffic, and approximately how many hidden services the relay has seen\&. .RE .PP -\fIDataDirectory\fR/\fBnetworkstatus\-bridges`\fR +\fIDataDirectory\fR/\fBnetworkstatus\-bridges\fR .RS 4 Only used by authoritative bridge directories\&. Contains information about bridges that have self\-reported themselves to the bridge authority\&. .RE diff -Nru tor-0.4.8.16/doc/man/tor.1.txt tor-0.4.9.6/doc/man/tor.1.txt --- tor-0.4.8.16/doc/man/tor.1.txt 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/doc/man/tor.1.txt 2026-03-25 14:30:34.000000000 +0000 @@ -168,6 +168,16 @@ make sure that they are owned by the user actually running the Tor daemon on your system. +[[opt-keygen-family]] **`--keygen-family`** __basename__:: + Generate a new family ID key in __basename__`.secret_family_key`. + To use this key, install it on every relay in your family. + (Put it in the relay's `KeyDirectory`.) + Also, store the corresponding family ID in __basename__`.public_family_id`. + Then enable the corresponding FamilyID option on your relays. + This command overwrites these files if they already exist. + See https://community.torproject.org/relay/setup/post-install/family-ids/ + for more information. + **`--passphrase-fd`** __FILEDES__:: File descriptor to read the passphrase from. Note that unlike with the tor-gencert program, the entire file contents are read and used as @@ -906,7 +916,8 @@ set to 1, all potentially sensitive strings are replaced. If it is set to relay, all log messages generated when acting as a relay are sanitized, but all messages generated when acting as a client are not. - Note: Tor may not heed this option when logging at log levels below Notice. + Note: Tor may not heed this option when logging at log levels more + verbose than Notice. (Default: 1) [[Sandbox]] **Sandbox** **0**|**1**:: @@ -1010,7 +1021,7 @@ equivalent option for directory connections, because all Tor client versions that support this option download directory documents via OR connections. + + - The only protocol supported right now 'haproxy'. This option is only for + The only protocol supported right now is 'haproxy'. This option is only for clients. (Default: none) + + The HAProxy version 1 proxy protocol is described in detail at @@ -2385,6 +2396,16 @@ policy options are set, Tor behaves as if ExitRelay were set to 0. (Default: auto) +[[ReevaluateExitPolicy]] **ReevaluateExitPolicy** **0**|**1**:: + If set, reevaluate the exit policy on existing connections when reloading + configuration. + + + + When the exit policy of an exit node change while reloading configuration, + connections made prior to this change could violate the new policy. By + setting this to 1, Tor will check if such connections exist, and mark them + for termination. + (Default: 0) + [[ExtendAllowPrivateAddresses]] **ExtendAllowPrivateAddresses** **0**|**1**:: When this option is enabled, Tor will connect to relays on localhost, RFC1918 addresses, and so on. In particular, Tor will make direct OR @@ -2429,6 +2450,16 @@ level __notice__ message designed to help developers instrumenting Tor's main event loop. (Default: 0) +[[MaxHSDirCacheBytes]] **MaxHSDirCacheBytes** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**:: + This option configures a threshold of Hidden Service Directory memory + consumption above which your Tor relay will begin to prune the least-frequently + accessed hidden service descriptors from the relay's HSDir cache. + If set to 0, this will default to 20% of MaxMemInQueues. (Default: 0) + + + + This pruning used to be done as part of MaxMemInQueues, but it has been + decoupled to allow more fine-grained control of descriptor cache size under + DDoS conditions. + [[MaxMemInQueues]] **MaxMemInQueues** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**:: This option configures a threshold above which Tor will assume that it needs to stop queueing or buffering data because it's about to run out of @@ -2462,6 +2493,40 @@ Note: do not use MyFamily when configuring your Tor instance as a bridge. +[[FamilyId]] **FamilyId** __ident__:: + Configure this relay to be part of a family + identified by a shared secret family key with the given key identity. + A corresponding family key must be stored in the relay's key directory, + with a filename ending with ".secret\_family\_key". + This option can appear multiple times. + Family keys are generated with "--keygen-family"; + this also generates the value you should use in the __ident__ field + in a file ending with ".public\_family\_id". + For information on generating and installing a family + key, see https://community.torproject.org/relay/setup/post-install/family-ids/ + + + In the future, this will be the preferred way for relays + to advertise family membership. + But for now, relay families should configure + both this option _and_ MyFamily, so older clients + will still recognize the relays' family membership. + + + (Note that if the seccomp2 Sandbox feature is enabled, + it is not possible to change the key filenames while Tor is running.) + +[[FamilyIdStar]] **FamilyId** ** * **:: + Configure this relay to be part of _every_ family + identified by any family ID key found in the family key directory. + Only filenames ending with ".secret\_family\_key" are considered. + Specifying family IDs in this way makes it unnecessary to adjust the + configuration file if the family key is rotated, + but it increases the likelihood of accidentally using a different + set of family keys than the ones you had expected. + +[[FamilyKeyDirectory]] **FamilyKeyDirectory** __directory__: + Configure a directory to use, in place of the key directory, + when searching for family ID keys. + [[Nickname]] **Nickname** __name__:: Set the server's nickname to \'name'. Nicknames must be between 1 and 19 characters inclusive, and must contain only the characters [a-zA-Z0-9]. @@ -3026,6 +3091,44 @@ consensus parameter. If not defined in the consensus, the value is 0. (Default: auto) +The following options are useful only for a exit relay. + +[[DoSStreamCreationEnabled]] **DoSStreamCreationEnabled** **0**|**1**|**auto**:: + + Enable the stream DoS mitigation. If set to 1 (enabled), tor will apply + rate limit on the creation of new streams and dns requests per circuit. + "auto" means use the consensus parameter. If not defined in the consensus, + the value is 0. (Default: auto) + +[[DoSStreamCreationDefenseType]] **DoSStreamCreationDefenseType** __NUM__:: + + This is the type of defense applied to a detected circuit or stream for the + stream mitigation. The possible values are: + + + 1: No defense. + + + 2: Reject the stream or resolve request. + + + 3: Close the circuit creating too many streams. + + + "0" means use the consensus parameter. If not defined in the consensus, the value is 2. + (Default: 0) + +[[DoSStreamCreationRate]] **DoSStreamCreationRate** __NUM__:: + + The allowed rate of stream creation from a single circuit per second. Coupled + with the burst (see below), if the limit is reached, actions can be taken + against the stream or circuit (DoSStreamCreationDefenseType). If not defined or + set to 0, it is controlled by a consensus parameter. If not defined in the + consensus, the value is 100. (Default: 0) + +[[DoSStreamCreationBurst]] **DoSStreamCreationBurst** __NUM__:: + + The allowed burst of stream creation from a circuit per second. + See the DoSStreamCreationRate for more details on this detection. If + not defined or set to 0, it is controlled by a consensus parameter. If not + defined in the consensus, the value is 300. (Default: 0) + For onion services, mitigations are a work in progress and multiple options are currently available. @@ -3080,7 +3183,7 @@ Why is this not helping reachability of the service? Because the defenses are at the introduction point, an attacker can easily flood all introduction point rendering the service unavailable due to no client being able to pass through. -But, the service itself is not overwhelmed with connetions allowing it to +But, the service itself is not overwhelmed with connections allowing it to function properly for the few clients that were able to go through or other any services running on the same tor instance. @@ -3252,7 +3355,7 @@ If set, the directory authority will start rejecting directory requests from non relay connections by sending a 503 error code if it is under bandwidth pressure (reaching the configured limit if any). Relays will - always tried to be answered even if this is on. (Default: 1) + always be answered even if this is on. (Default: 1) //Out of order because it logically belongs with the other CCs options. [[AuthDirBadExitCCs]] **AuthDirBadExitCCs** __CC__,... + @@ -3370,6 +3473,11 @@ multiple times: the values from multiple lines are spliced together. When this is set then **VersioningAuthoritativeDirectory** should be set too. +[[MinimalAcceptedServerVersion]] **MinimalAcceptedServerVersion** __STRING__:: + STRING is the oldest Tor version accepted by the directory authority for + relays and bridge. Any older version will be rejected. + (Default: 0.4.7.0-alpha-dev) + [[V3AuthDistDelay]] **V3AuthDistDelay** __N__ **seconds**|**minutes**|**hours**:: V3 authoritative directories only. Configures the server's preferred delay between publishing its consensus and signature and assuming it has all the @@ -3987,6 +4095,12 @@ generated key, which the relay uses to handle any requests that were made by clients that didn't have the new one. +__KeyDirectory__/__keyname__**`.secret_family_key`**:: + A relay family's family identity key. + Used to prove membership in a relay family. + See https://community.torproject.org/relay/setup/post-install/family-ids/ + for more information. + __DataDirectory__/**`fingerprint`**:: Only used by servers. Contains the fingerprint of the server's RSA identity key. @@ -3999,6 +4113,10 @@ Only used by bridges. Contains the hashed fingerprint of the bridge's identity key. (That is, the hash of the hash of the identity key.) +__DataDirectory__/**`bridgelines`**:: + Only used by bridges. Contains the bridge lines that clients can use to + connect using pluggable transports. + __DataDirectory__/**`approved-routers`**:: Only used by authoritative directory servers. Each line lists a status and an identity, separated by whitespace. Identities can be hex-encoded RSA @@ -4064,7 +4182,7 @@ of what fraction of the traffic is hidden service rendezvous traffic, and approximately how many hidden services the relay has seen. -__DataDirectory__/**networkstatus-bridges`**:: +__DataDirectory__/**`networkstatus-bridges`**:: Only used by authoritative bridge directories. Contains information about bridges that have self-reported themselves to the bridge authority. diff -Nru tor-0.4.8.16/doc/man/tor.html.in tor-0.4.9.6/doc/man/tor.html.in --- tor-0.4.8.16/doc/man/tor.html.in 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/doc/man/tor.html.in 2026-03-25 14:30:34.000000000 +0000 @@ -1008,6 +1008,21 @@ daemon on your system.

+ --keygen-family basename +
+
+

+ Generate a new family ID key in basename.secret_family_key. + To use this key, install it on every relay in your family. + (Put it in the relay’s KeyDirectory.) + Also, store the corresponding family ID in basename.public_family_id. + Then enable the corresponding FamilyID option on your relays. + This command overwrites these files if they already exist. + See https://community.torproject.org/relay/setup/post-install/family-ids/ + for more information. +

+
+
--passphrase-fd FILEDES
@@ -2148,7 +2163,8 @@ set to 1, all potentially sensitive strings are replaced. If it is set to relay, all log messages generated when acting as a relay are sanitized, but all messages generated when acting as a client are not. - Note: Tor may not heed this option when logging at log levels below Notice. + Note: Tor may not heed this option when logging at log levels more + verbose than Notice. (Default: 1)

@@ -2301,7 +2317,7 @@

-
The only protocol supported right now 'haproxy'. This option is only for
+
The only protocol supported right now is 'haproxy'. This option is only for
 clients. (Default: none) +
@@ -4419,6 +4435,21 @@

+ ReevaluateExitPolicy 0|1 +
+
+

+ If set, reevaluate the exit policy on existing connections when reloading + configuration.
+
+ When the exit policy of an exit node change while reloading configuration, + connections made prior to this change could violate the new policy. By + setting this to 1, Tor will check if such connections exist, and mark them + for termination. + (Default: 0) +

+
+
ExtendAllowPrivateAddresses 0|1
@@ -4503,6 +4534,21 @@

+ MaxHSDirCacheBytes N bytes|KBytes|MBytes|GBytes +
+
+

+ This option configures a threshold of Hidden Service Directory memory + consumption above which your Tor relay will begin to prune the least-frequently + accessed hidden service descriptors from the relay’s HSDir cache. + If set to 0, this will default to 20% of MaxMemInQueues. (Default: 0)
+
+ This pruning used to be done as part of MaxMemInQueues, but it has been + decoupled to allow more fine-grained control of descriptor cache size under + DDoS conditions. +

+
+
MaxMemInQueues N bytes|KBytes|MBytes|GBytes
@@ -4551,6 +4597,51 @@

+ FamilyId ident +
+
+

+ Configure this relay to be part of a family + identified by a shared secret family key with the given key identity. + A corresponding family key must be stored in the relay’s key directory, + with a filename ending with ".secret_family_key". + This option can appear multiple times. + Family keys are generated with "--keygen-family"; + this also generates the value you should use in the ident field + in a file ending with ".public_family_id". + For information on generating and installing a family + key, see https://community.torproject.org/relay/setup/post-install/family-ids/ +
+ In the future, this will be the preferred way for relays + to advertise family membership. + But for now, relay families should configure + both this option and MyFamily, so older clients + will still recognize the relays' family membership. +
+ (Note that if the seccomp2 Sandbox feature is enabled, + it is not possible to change the key filenames while Tor is running.) +

+
+
+ FamilyId * +
+
+

+ Configure this relay to be part of every family + identified by any family ID key found in the family key directory. + Only filenames ending with ".secret\_family\_key" are considered. + Specifying family IDs in this way makes it unnecessary to adjust the + configuration file if the family key is rotated, + but it increases the likelihood of accidentally using a different + set of family keys than the ones you had expected. +

+
+
+

FamilyKeyDirectory directory: + Configure a directory to use, in place of the key directory, + when searching for family ID keys.

+
+
Nickname name
@@ -5411,6 +5502,61 @@

+

The following options are useful only for a exit relay.

+
+
+ DoSStreamCreationEnabled 0|1|auto +
+
+

+ Enable the stream DoS mitigation. If set to 1 (enabled), tor will apply + rate limit on the creation of new streams and dns requests per circuit. + "auto" means use the consensus parameter. If not defined in the consensus, + the value is 0. (Default: auto) +

+
+
+ DoSStreamCreationDefenseType NUM +
+
+

+ This is the type of defense applied to a detected circuit or stream for the + stream mitigation. The possible values are: +
+ 1: No defense. +
+ 2: Reject the stream or resolve request. +
+ 3: Close the circuit creating too many streams. +
+ "0" means use the consensus parameter. If not defined in the consensus, the value is 2. + (Default: 0) +

+
+
+ DoSStreamCreationRate NUM +
+
+

+ The allowed rate of stream creation from a single circuit per second. Coupled + with the burst (see below), if the limit is reached, actions can be taken + against the stream or circuit (DoSStreamCreationDefenseType). If not defined or + set to 0, it is controlled by a consensus parameter. If not defined in the + consensus, the value is 100. (Default: 0) +

+
+
+ DoSStreamCreationBurst NUM +
+
+

+ The allowed burst of stream creation from a circuit per second. + See the DoSStreamCreationRate for more details on this detection. If + not defined or set to 0, it is controlled by a consensus parameter. If not + defined in the consensus, the value is 300. (Default: 0) +

+
+

For onion services, mitigations are a work in progress and multiple options are currently available.

The introduction point defense is a rate limit on the number of introduction @@ -5476,7 +5622,7 @@

Why is this not helping reachability of the service? Because the defenses are at the introduction point, an attacker can easily flood all introduction point rendering the service unavailable due to no client being able to pass through. -But, the service itself is not overwhelmed with connetions allowing it to +But, the service itself is not overwhelmed with connections allowing it to function properly for the few clients that were able to go through or other any services running on the same tor instance.

The bottom line is that this protects the network by preventing an onion @@ -5749,7 +5895,7 @@ If set, the directory authority will start rejecting directory requests from non relay connections by sending a 503 error code if it is under bandwidth pressure (reaching the configured limit if any). Relays will - always tried to be answered even if this is on. (Default: 1) + always be answered even if this is on. (Default: 1)

@@ -5960,6 +6106,16 @@

+ MinimalAcceptedServerVersion STRING +
+
+

+ STRING is the oldest Tor version accepted by the directory authority for + relays and bridge. Any older version will be rejected. + (Default: 0.4.7.0-alpha-dev) +

+
+
V3AuthDistDelay N seconds|minutes|hours
@@ -7053,6 +7209,17 @@

+KeyDirectory/keyname.secret_family_key +
+
+

+ A relay family’s family identity key. + Used to prove membership in a relay family. + See https://community.torproject.org/relay/setup/post-install/family-ids/ + for more information. +

+
+
DataDirectory/fingerprint
@@ -7080,6 +7247,15 @@

+DataDirectory/bridgelines +
+
+

+ Only used by bridges. Contains the bridge lines that clients can use to + connect using pluggable transports. +

+
+
DataDirectory/approved-routers
@@ -7210,7 +7386,7 @@

-DataDirectory/networkstatus-bridges` +DataDirectory/networkstatus-bridges

diff -Nru tor-0.4.8.16/doc/man/torify.1.in tor-0.4.9.6/doc/man/torify.1.in --- tor-0.4.8.16/doc/man/torify.1.in 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/doc/man/torify.1.in 2026-03-25 14:30:34.000000000 +0000 @@ -2,12 +2,12 @@ .\" Title: torify .\" Author: Tor Project, Inc. .\" Generator: DocBook XSL Stylesheets vsnapshot -.\" Date: 03/24/2025 +.\" Date: 03/25/2026 .\" Manual: Tor Manual .\" Source: Tor .\" Language: English .\" -.TH "TORIFY" "1" "03/24/2025" "Tor" "Tor Manual" +.TH "TORIFY" "1" "03/25/2026" "Tor" "Tor Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- diff -Nru tor-0.4.8.16/m4/ax_check_compile_flag.m4 tor-0.4.9.6/m4/ax_check_compile_flag.m4 --- tor-0.4.8.16/m4/ax_check_compile_flag.m4 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/m4/ax_check_compile_flag.m4 2026-03-25 14:30:34.000000000 +0000 @@ -1,43 +1,45 @@ - # Copyright (c) 2008 Guido U. Draheim - # Copyright (c) 2011 Maarten Bosmans - # - # 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 3 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, see . - # - # As a special exception, the respective Autoconf Macro's copyright owner - # gives unlimited permission to copy, distribute and modify the configure - # scripts that are the output of Autoconf when processing the Macro. You - # need not follow the terms of the GNU General Public License when using - # or distributing such scripts, even though portions of the text of the - # Macro appear in them. The GNU General Public License (GPL) does govern - # all other use of the material that constitutes the Autoconf Macro. - # - # This special exception to the GPL applies to versions of the Autoconf - # Macro released by the Autoconf Archive. When you make and distribute a - # modified version of the Autoconf Macro, you may extend this special - # exception to the GPL to apply to your modified version as well. - # Copying and distribution of this file, with or without modification, are - # permitted in any medium without royalty provided the copyright notice - # and this notice are preserved. This file is offered as-is, without any - # warranty. +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) +# +# DESCRIPTION +# +# Check whether the given FLAG works with the current language's compiler +# or gives an error. (Warnings, however, are ignored) +# +# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on +# success/failure. +# +# If EXTRA-FLAGS is defined, it is added to the current language's default +# flags (e.g. CFLAGS) when the check is done. The check is thus made with +# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to +# force the compiler to issue an error when a bad flag is given. +# +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# +# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this +# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. +# +# LICENSE +# +# Copyright (c) 2008 Guido U. Draheim +# Copyright (c) 2011 Maarten Bosmans +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. - #serial 5 - #serial 6 +#serial 7 - AC_DEFUN([AX_CHECK_COMPILE_FLAG], - [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AC_DEFUN([AX_CHECK_COMPILE_FLAG], +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl -AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ +AC_CACHE_CHECK([whether the _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], diff -Nru tor-0.4.8.16/orconfig.h.in tor-0.4.9.6/orconfig.h.in --- tor-0.4.8.16/orconfig.h.in 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/orconfig.h.in 2026-03-25 14:30:34.000000000 +0000 @@ -6,7 +6,7 @@ /* All assert failures are fatal */ #undef ALL_BUGS_ARE_FATAL -/* # for 0.4.8.16 Approximate date when this software was released. (Updated +/* # for 0.4.9.6 Approximate date when this software was released. (Updated when the version changes.) */ #undef APPROX_RELEASE_DATE @@ -95,6 +95,9 @@ /* defined if we have the fallthrough attribute. */ #undef HAVE_ATTR_FALLTHROUGH +/* defined if we have the nonstring attribute. */ +#undef HAVE_ATTR_NONSTRING + /* Define to 1 if you have the `backtrace' function. */ #undef HAVE_BACKTRACE @@ -141,9 +144,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_ERRNO_H -/* Define to 1 if you have the `ERR_load_KDF_strings' function. */ -#undef HAVE_ERR_LOAD_KDF_STRINGS - /* Define to 1 if you have the `evdns_base_get_nameserver_addr' function. */ #undef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR @@ -381,6 +381,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NET_PFVAR_H +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_ENGINE_H + /* Define to 1 if you have the `pipe' function. */ #undef HAVE_PIPE @@ -441,29 +444,11 @@ /* Define to 1 if the system has the type `ssize_t'. */ #undef HAVE_SSIZE_T -/* Define to 1 if you have the `SSL_CIPHER_find' function. */ -#undef HAVE_SSL_CIPHER_FIND - -/* Define to 1 if you have the `SSL_CTX_set1_groups_list' function. */ -#undef HAVE_SSL_CTX_SET1_GROUPS_LIST - /* Define to 1 if you have the `SSL_CTX_set_security_level' function. */ #undef HAVE_SSL_CTX_SET_SECURITY_LEVEL -/* Define to 1 if you have the `SSL_get_client_ciphers' function. */ -#undef HAVE_SSL_GET_CLIENT_CIPHERS - -/* Define to 1 if you have the `SSL_get_client_random' function. */ -#undef HAVE_SSL_GET_CLIENT_RANDOM - -/* Define to 1 if you have the `SSL_get_server_random' function. */ -#undef HAVE_SSL_GET_SERVER_RANDOM - -/* Define to 1 if you have the `SSL_SESSION_get_master_key' function. */ -#undef HAVE_SSL_SESSION_GET_MASTER_KEY - -/* Define to 1 if `state' is a member of `SSL'. */ -#undef HAVE_SSL_STATE +/* Define to 1 if you have the `SSL_set_ciphersuites' function. */ +#undef HAVE_SSL_SET_CIPHERSUITES /* Define to 1 if you have the `statvfs' function. */ #undef HAVE_STATVFS @@ -525,10 +510,6 @@ /* Define to 1 if `sin_len' is a member of `struct sockaddr_in'. */ #undef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN -/* Define to 1 if `get_cipher_by_char' is a member of `struct ssl_method_st'. - */ -#undef HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR - /* Define to 1 if `tcpi_snd_mss' is a member of `struct tcp_info'. */ #undef HAVE_STRUCT_TCP_INFO_TCPI_SND_MSS @@ -634,9 +615,6 @@ /* Define to 1 if you have the `timingsafe_memcmp' function. */ #undef HAVE_TIMINGSAFE_MEMCMP -/* Define to 1 if you have the `TLS_method' function. */ -#undef HAVE_TLS_METHOD - /* Compiled with tracing support */ #undef HAVE_TRACING @@ -691,6 +669,9 @@ /* Define to 1 iff malloc(0) returns a pointer */ #undef MALLOC_ZERO_WORKS +/* whether nss defines ecdh_hybrid key exchange. */ +#undef NSS_HAS_ECDH_HYBRID + /* Define to 1 iff memset(0) sets pointers to NULL */ #undef NULL_REP_IS_ZERO_BYTES @@ -742,9 +723,6 @@ /* The size of `pid_t', as computed by sizeof. */ #undef SIZEOF_PID_T -/* The size of `SHA_CTX', as computed by sizeof. */ -#undef SIZEOF_SHA_CTX - /* The size of `short', as computed by sizeof. */ #undef SIZEOF_SHORT diff -Nru tor-0.4.8.16/scripts/maint/practracker/practracker.py tor-0.4.9.6/scripts/maint/practracker/practracker.py --- tor-0.4.8.16/scripts/maint/practracker/practracker.py 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/scripts/maint/practracker/practracker.py 2026-03-25 14:30:34.000000000 +0000 @@ -24,7 +24,7 @@ from __future__ import print_function from __future__ import unicode_literals -import codecs, os, sys +import io, os, sys import metrics import util @@ -64,7 +64,7 @@ ####################################################### def open_file(fname): - return codecs.open(fname, 'r', encoding='utf-8') + return io.open(fname, 'r', encoding='utf-8') def consider_file_size(fname, f): """Consider the size of 'f' and yield an FileSizeItem for it. diff -Nru tor-0.4.8.16/src/app/config/config.c tor-0.4.9.6/src/app/config/config.c --- tor-0.4.8.16/src/app/config/config.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/app/config/config.c 2026-03-25 14:30:34.000000000 +0000 @@ -470,6 +470,9 @@ V(UseDefaultFallbackDirs, BOOL, "1"), OBSOLETE("FallbackNetworkstatusFile"), + VAR("FamilyId", LINELIST, FamilyId_lines, NULL), + VAR_IMMUTABLE("FamilyKeyDirectory", + FILENAME, FamilyKeyDirectory_option, NULL), V(FascistFirewall, BOOL, "0"), V(FirewallPorts, CSV, ""), OBSOLETE("FastFirstHopPK"), @@ -483,6 +486,13 @@ #ifdef _WIN32 V(GeoIPFile, FILENAME, ""), V(GeoIPv6File, FILENAME, ""), +#elif defined(__ANDROID__) + /* Android apps use paths that are configured at runtime. + * /data/local/tmp is guaranteed to exist, but will only be + * usable by the 'shell' and 'root' users, so this fallback is + * for debugging only. */ + V(GeoIPFile, FILENAME, "/data/local/tmp/geoip"), + V(GeoIPv6File, FILENAME, "/data/local/tmp/geoip6"), #else V(GeoIPFile, FILENAME, SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"), @@ -558,6 +568,7 @@ V(MaxClientCircuitsPending, POSINT, "32"), V(MaxConsensusAgeForDiffs, INTERVAL, "0 seconds"), VAR("MaxMemInQueues", MEMUNIT, MaxMemInQueues_raw, "0"), + VAR("MaxHSDirCacheBytes", MEMUNIT, MaxHSDirCacheBytes, "0"), OBSOLETE("MaxOnionsPending"), V(MaxOnionQueueDelay, MSEC_INTERVAL, "0"), V(MaxUnparseableDescSizeToLog, MEMUNIT, "10 MB"), @@ -637,6 +648,7 @@ V(RephistTrackTime, INTERVAL, "24 hours"), V_IMMUTABLE(RunAsDaemon, BOOL, "0"), V(ReducedExitPolicy, BOOL, "0"), + V(ReevaluateExitPolicy, BOOL, "0"), OBSOLETE("RunTesting"), // currently unused V_IMMUTABLE(Sandbox, BOOL, "0"), V(SafeLogging, STRING, "1"), @@ -996,6 +1008,7 @@ config_line_t *changes = config_get_changes(get_options_mgr(), old_options, new_val); control_event_conf_changed(changes); + connection_reapply_exit_policy(changes); config_free_lines(changes); } @@ -1035,11 +1048,17 @@ } tor_free(options->DataDirectory); tor_free(options->CacheDirectory); + tor_free(options->FamilyKeyDirectory); tor_free(options->KeyDirectory); tor_free(options->BridgePassword_AuthDigest_); tor_free(options->command_arg); tor_free(options->master_key_fname); config_free_lines(options->MyFamily); + if (options->FamilyIds) { + SMARTLIST_FOREACH(options->FamilyIds, + ed25519_public_key_t *, k, tor_free(k)); + smartlist_free(options->FamilyIds); + } } /** Release all memory allocated in options @@ -2479,6 +2498,9 @@ .command=CMD_LIST_FINGERPRINT }, { .name="--keygen", .command=CMD_KEYGEN }, + { .name="--keygen-family", + .command=CMD_KEYGEN_FAMILY, + .takes_argument=ARGUMENT_NECESSARY }, { .name="--key-expiration", .takes_argument=ARGUMENT_OPTIONAL, .command=CMD_KEY_EXPIRATION }, @@ -6898,6 +6920,15 @@ } else { return tor_strdup(get_windows_conf_root()); } +#elif defined(__ANDROID__) + /* Android apps can only use paths that are configured at runtime. + * /data/local/tmp is guaranteed to exist, but is only usable by the + * 'shell' and 'root' users, so this fallback is for debugging only. */ + if (val) { + return tor_strdup(val); + } else { + return tor_strdup("/data/local/tmp"); + } #else /* !defined(_WIN32) */ const char *d = val; if (!d) @@ -6962,6 +6993,17 @@ options->CacheDirectory = tor_strdup(options->DataDirectory); } + tor_free(options->FamilyKeyDirectory); + if (options->FamilyKeyDirectory_option) { + options->FamilyKeyDirectory = + get_data_directory(options->FamilyKeyDirectory_option); + if (!options->FamilyKeyDirectory) + return -1; + } else { + /* Default to the key directory. */ + options->FamilyKeyDirectory = tor_strdup(options->KeyDirectory); + } + return 0; } diff -Nru tor-0.4.8.16/src/app/config/fallback_dirs.inc tor-0.4.9.6/src/app/config/fallback_dirs.inc --- tor-0.4.8.16/src/app/config/fallback_dirs.inc 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/app/config/fallback_dirs.inc 2026-03-25 14:30:34.000000000 +0000 @@ -3,1104 +3,1108 @@ /* timestamp=20210412000000 */ /* source=offer-list */ // -// Generated on: Thu, 20 Mar 2025 14:40:50 +0000 +// Generated on: Wed, 25 Mar 2026 14:14:46 +0000 -"154.53.164.216 orport=9090 id=C90A0A41CE492723902DC55B2512A608FE733F0E" -/* nickname=ren */ +"46.232.251.183 orport=9001 id=66EEF68A3307E63D59CE34969A710F1FA697DE83" +" ipv6=[2a03:4000:2b:41f:0:1d:0:fe]:9001" +/* nickname=theonlyone */ /* extrainfo=0 */ /* ===== */ , -"185.225.18.102 orport=9001 id=2FA6A81D52476C4D64ED5F385CBF5FBE4937F4CB" -/* nickname=gralrush */ +"109.70.100.245 orport=443 id=9E03B94B16FF39EA2019CE7BF5C6C8BBF84CD675" +" ipv6=[2a03:e600:100:c3::10]:443" +/* nickname=lamarr */ /* extrainfo=0 */ /* ===== */ , -"45.141.215.95 orport=9100 id=80F322ED0995F27CD26B5A9DE7B804F92E8ACA94" -" ipv6=[2a12:a800:2:1:45:141:215:95]:9100" -/* nickname=Quetzalcoatl */ -/* extrainfo=0 */ -/* ===== */ -, -"68.71.25.194 orport=9007 id=9A3776C96E94D7EEBE2A3FA4CA4EA4E6DC0DC4AF" -/* nickname=FuckWater */ +"64.65.1.64 orport=443 id=55B3EAD57AF13B6306ACF59ECCDC5E6E24EF575A" +/* nickname=wifisfuneral */ /* extrainfo=0 */ /* ===== */ , -"2.58.56.220 orport=8430 id=7F35906CE8E33C7FB60E9EA12101AB4CBE13403C" -" ipv6=[2a12:a800:1:1:2:58:56:220]:8430" -/* nickname=Quetzalcoatl */ +"141.95.86.17 orport=9001 id=C94D0985BD317B514DDBED8ECD5EC99FB60DD1F6" +" ipv6=[2001:41d0:701:1100::5a30]:9001" +/* nickname=DemonsysEU */ /* extrainfo=0 */ /* ===== */ , -"158.69.204.36 orport=80 id=C7A46C866B963FC0F5C0E9DCE375C869D40F23E4" -/* nickname=stars2 */ +"64.65.1.67 orport=443 id=4A167C3AA47077BA679DDFA3167CF98464CEAFE5" +/* nickname=ralofamerica */ /* extrainfo=0 */ /* ===== */ , -"46.229.55.118 orport=9001 id=FE857C3043412FD5454ED5FEF55C4C572E5B70CF" -/* nickname=volodymir */ +"192.121.108.118 orport=9001 id=A02AB2C40AB744F451CCCE38781D8E05676CC15E" +" ipv6=[2a09:be40:28fb:1337::f00d]:9001" +/* nickname=Relay06MaskAD */ /* extrainfo=0 */ /* ===== */ , -"135.148.100.233 orport=443 id=EFC68FF70A36CF8DE5E8437F2DCCFADF7A94A421" -" ipv6=[2604:2dc0:100:38e9::1]:443" -/* nickname=null */ +"62.66.145.248 orport=9001 id=32D6F1E338860568A1E3CA1CFD4D84EC7485EC34" +/* nickname=LilleVemmelund */ /* extrainfo=0 */ /* ===== */ , -"204.8.96.158 orport=443 id=90BF7147B422A1BABEFA503656EBD17987424441" -" ipv6=[2620:7:6001::158]:80" -/* nickname=Quintex69 */ +"194.147.140.102 orport=995 id=2C6D0929C0D00B3461670AF874B5418164A7D1F2" +" ipv6=[2001:67c:440:f887:194:147:140:102]:995" +/* nickname=tor102 */ /* extrainfo=0 */ /* ===== */ , -"82.149.227.126 orport=443 id=CF6A6080091BB210AA3892FEFE2F6A396DA08DF3" -" ipv6=[2a01:440:108:11:82:149:227:126]:443" -/* nickname=cryzrelay01 */ +"45.84.107.84 orport=443 id=9CB75E6343DDB8E38F78A20E9525604F05988FA2" +/* nickname=MicrosoftSucks */ /* extrainfo=0 */ /* ===== */ , -"192.42.116.189 orport=9003 id=F7B94B1A67B563459C6A7C6AD7D5B8031E127B26" -" ipv6=[2001:67c:6ec:203:192:42:116:189]:9003" -/* nickname=NTH37R4 */ +"5.255.127.222 orport=9001 id=4B61EC04E1797D8688475BD24EDA450914497D84" +/* nickname=Dopamine */ /* extrainfo=0 */ /* ===== */ , -"51.210.179.144 orport=9000 id=698EB2D58F67A26E4EEB93B302DBB67E46B6AA34" -/* nickname=prsv */ +"45.80.158.93 orport=143 id=F260B54AD13D7A9AAA72E67DD583F30037EF7FFA" +" ipv6=[2a12:a800:2:1:45:80:158:93]:143" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"45.145.166.175 orport=9000 id=AF90C647D5AE15BD1D8ED81845D49E2F4F181884" -" ipv6=[2a04:ecc0:8:a8:4567:fd2e:0:1]:9000" -/* nickname=prsv */ +"45.138.16.107 orport=9100 id=D88B5B35EF4D5EF11F5B670C364F812D0349B8DB" +" ipv6=[2a12:a800:2:1:45:138:16:107]:9100" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"137.226.34.45 orport=9005 id=27E1B97D9491013EF48479D4F47002F3358E0D92" -" ipv6=[2a00:8a60:e012:a00::9001]:9005" -/* nickname=FTPhalifaxRWTH */ +"45.95.169.43 orport=9001 id=213038B323FF8737A55C9DA15FEA1C9BBC4785D3" +/* nickname=Challanger */ /* extrainfo=0 */ /* ===== */ , -"88.151.194.118 orport=443 id=7B842FB48CFF19898C8336A11CAA3F425C90F9B5" -/* nickname=BiggerBetter */ +"66.42.113.136 orport=443 id=D1D586F7356CD497AA7344A1A04F16B62B97E3C5" +/* nickname=marleybone3a */ /* extrainfo=0 */ /* ===== */ , -"94.23.172.32 orport=444 id=799ECF332DECA02C49DE21FF022F7E2DBECDA771" -/* nickname=Waeswynn */ +"171.25.193.131 orport=443 id=8F1C04C57F554DBCA7E02F6BC200AA474DC833AE" +" ipv6=[2001:67c:289c:4::132]:443" +/* nickname=DFRI126 */ /* extrainfo=0 */ /* ===== */ , -"217.160.247.34 orport=9001 id=11AC67307B362B77569AF314A9A7A06B9195DF19" -" ipv6=[2a01:239:2b6:b400::1]:9001" -/* nickname=jhsthirdtorrelay */ +"23.129.64.176 orport=443 id=E234C5568893454711240DAD886FE315EF275DDB" +" ipv6=[2620:18c:0:192::e0:176]:443" +/* nickname=dimensiondoor */ /* extrainfo=0 */ /* ===== */ , -"185.220.101.96 orport=993 id=C688B3EF9AB0354EB2794174519BB9ED9E6467E7" -" ipv6=[2a0b:f4c2:4::96]:993" -/* nickname=Digitalcourage4ipab */ +"62.72.47.105 orport=8100 id=9DA3641B237AF84095C3D057F472106F1E32CCB0" +" ipv6=[2407:3640:2259:6302::1]:8100" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"37.48.90.84 orport=9001 id=C1F9375437CAA5C5BF1AA4C8E78107BF61883FD5" -/* nickname=ThePlace */ +"185.232.68.247 orport=443 id=F31A8ECBF669CC4E6B1C14866EBD25C13A70F296" +" ipv6=[2a03:4000:4e:f3:689c:c6ff:fe24:89b4]:443" +/* nickname=CryptoCactus */ /* extrainfo=0 */ /* ===== */ , -"194.147.140.106 orport=993 id=6259DA604D98D6FE14AB557BB6479BA75FC43558" -" ipv6=[2001:67c:440:f887:194:147:140:106]:993" -/* nickname=tor106 */ +"82.160.220.21 orport=9001 id=A262706ED4F731025FAFBF56636C224EEF51B127" +/* nickname=speedtest10ge */ /* extrainfo=0 */ /* ===== */ , -"185.40.4.101 orport=444 id=E6B550BFD6A35725EFADA0DFD07511532FC18AE8" -" ipv6=[2a0e:4005:1002:ffff:185:40:4:101]:444" +"95.214.53.96 orport=8447 id=FD4831DD801161346FACD52452633088EA356271" +" ipv6=[2a03:cfc0:8000:7::5fd6:3560]:8447" /* nickname=bauruine */ /* extrainfo=0 */ /* ===== */ , -"45.141.215.114 orport=8100 id=74F49CD5F9E94EDBF1F8D8705B4C64E88C1CC344" -" ipv6=[2a12:a800:2:1:45:141:215:114]:8100" -/* nickname=Quetzalcoatl */ +"45.76.61.27 orport=9001 id=CA3A394AAF64EE2E91296348BBBC66DCCEAA5FA5" +/* nickname=ugh */ /* extrainfo=0 */ /* ===== */ , -"172.105.6.34 orport=9001 id=D7F59CFB13A93E4C0BF867374B66547E226A7255" -" ipv6=[2600:3c04::f03c:93ff:fece:e1d1]:9050" -/* nickname=AndroidFighter */ +"51.195.119.154 orport=9300 id=959779FD7167FD412B3B098457B04433F572AAEB" +" ipv6=[2001:41d0:701:1100::3231]:9300" +/* nickname=prsv */ /* extrainfo=0 */ /* ===== */ , -"5.199.162.155 orport=9001 id=6997013CB77B6F530540332626C23ACFE52C5096" -/* nickname=QuakeSARGE */ +"94.23.121.150 orport=8080 id=4D0F2ADB9CD55C3EBD14823D54B6541B99A51C19" +/* nickname=Unnamed */ /* extrainfo=0 */ /* ===== */ , -"103.251.167.20 orport=9001 id=30626238638AE65194814663A4651AFC04BC8D60" -" ipv6=[2a01:6340:2:501::20]:9001" -/* nickname=mentoreth */ +"124.198.131.173 orport=143 id=B6AF9746C05714E5B90063F44DC2C7FF5F96E051" +" ipv6=[2a12:a800:11:1:124:198:131:173]:143" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"185.241.208.204 orport=9200 id=2308F5B08A85F8600DEC23F9C127E1F16E988595" -" ipv6=[2a12:a800:2:1:185:241:208:204]:9200" -/* nickname=Aramis */ +"23.129.64.215 orport=443 id=3809938D5786CD2886C856578316AE3FF62FCCBD" +" ipv6=[2620:18c:0:192::e0:215]:443" +/* nickname=eo215 */ /* extrainfo=0 */ /* ===== */ , -"212.132.108.187 orport=443 id=D2A2E8F9CF83FBFF86C29612902F644AE9CB62DC" -/* nickname=tstarlit144 */ +"87.98.237.152 orport=9001 id=DFCE8C606B821A59D0E0E11AEF8C30FD22BBCC2B" +/* nickname=Unnamed */ /* extrainfo=0 */ /* ===== */ , -"80.64.181.152 orport=1025 id=61C52DFC090FD1B1AA0C1F431DC535249C311EB9" -" ipv6=[2a02:238:f04b:4125::]:1025" -/* nickname=Datenschredder */ +"104.244.79.44 orport=9100 id=CCCFD8D5FD21AC796234D914F1B7CC33ADCE52F8" +" ipv6=[2605:6400:30:f38b:28b3:cd24:51f3:e412]:9100" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"157.90.112.145 orport=9001 id=4E8BF739B5E7835776EDD72CF9CAA402ACE00055" -" ipv6=[2a01:4f8:c2c:e8a0::1]:9001" -/* nickname=COtto */ +"83.228.205.178 orport=8888 id=26C55AC78E6B2C3BB9DF304DBDD8A1E1D7D5F4DF" +" ipv6=[2001:1600:13:101::c39]:8888" +/* nickname=CyberDiplomacy */ /* extrainfo=0 */ /* ===== */ , -"185.82.126.13 orport=443 id=60553CA7FB840C5CDA60950E33C71585DF774258" -/* nickname=se4andersio */ +"194.26.192.186 orport=9200 id=1C62E9E7977A0C9B6F5D14FFCAF5515C95204C8D" +" ipv6=[2a12:a800:1:1:194:26:192:186]:9200" +/* nickname=prsv */ /* extrainfo=0 */ /* ===== */ , -"45.141.215.61 orport=7100 id=460D13CE3971BD2138760A892FBCF0F464C26F63" -" ipv6=[2a12:a800:2:1:45:141:215:61]:7100" -/* nickname=Quetzalcoatl */ +"46.20.33.223 orport=9100 id=B1AAE82FBCB8ECB429A6149626D3BB6410364EA1" +/* nickname=0uijabroad */ /* extrainfo=0 */ /* ===== */ , -"172.219.92.78 orport=9905 id=C0100C150EA96E1CBBBFB3B770EFCD50C5F55F8F" -/* nickname=hereyago */ +"46.4.74.237 orport=8080 id=4CF204F66452C89712B9CF513A213C1F03D8F706" +" ipv6=[2a01:4f8:140:522c::2]:8080" +/* nickname=Indigold */ /* extrainfo=0 */ /* ===== */ , -"184.174.38.53 orport=9001 id=A508096AA0C899F4E6ECD1D9C35037B89008BCBA" -" ipv6=[2a02:c206:3010:8083::1]:9001" -/* nickname=SafeAndEffective */ +"64.65.62.48 orport=443 id=EC488394FDF79BF2E846DA5D4148FC18163BB29B" +/* nickname=lildarkie */ /* extrainfo=0 */ /* ===== */ , -"37.59.29.77 orport=9111 id=371C00BF5F71AC45FBD5FE74504A6D2408BAD5E0" -/* nickname=Unnamed */ +"102.130.127.117 orport=443 id=26B466A5152B058DB26878731AE453D22A8F4B21" +/* nickname=alpha191 */ /* extrainfo=0 */ /* ===== */ , -"23.88.44.26 orport=6969 id=D22F93E2675F17BFF6D232F479B59E788FEAF903" -" ipv6=[2a01:4f8:c17:49c0::1]:6969" -/* nickname=sig9gianni */ +"192.42.116.45 orport=443 id=0DE135A4D0ECCB5D57F8B71BF8E22958FC4146A7" +" ipv6=[2001:67c:e60:c0c:192:42:116:45]:443" +/* nickname=NTH45R1 */ /* extrainfo=0 */ /* ===== */ , -"144.217.32.158 orport=9002 id=CB248D83FA220EE9DC0990A39C31A77F740874A0" -/* nickname=roomformushroom */ +"38.190.150.6 orport=9004 id=00E1290EBA8EE2D60119754DBD9AD1067B2A7712" +/* nickname=xkoloke */ /* extrainfo=0 */ /* ===== */ , -"185.220.101.73 orport=9000 id=2070E51315036FEB76FC2E0B03A320724234A9A4" -" ipv6=[2a0b:f4c2:3::73]:9000" -/* nickname=CCCStuttgartBer */ +"185.243.218.138 orport=443 id=EC99A6385A22B6A9552AB10DCFC37F1682BCB321" +" ipv6=[2a03:94e0:ffff:185:243:218:0:138]:443" +/* nickname=lukast */ /* extrainfo=0 */ /* ===== */ , -"131.188.40.188 orport=11180 id=EBE718E1A49EE229071702964F8DB1F318075FF8" -" ipv6=[2001:638:a000:4140::ffff:188]:11180" -/* nickname=fluxe4 */ +"185.227.70.134 orport=443 id=1F348BF999D4F7BE263270F5A24F69FCCEC1399C" +" ipv6=[2a12:bec0:20b:6b35::1]:443" +/* nickname=fluffypancakes006nl */ /* extrainfo=0 */ /* ===== */ , -"64.52.108.69 orport=443 id=64CB2B32C10ADD4B93D725B7DED238CCCD6D6DBA" -" ipv6=[2602:fc81:1:1::9:a600]:443" -/* nickname=permanentrecord */ +"45.80.158.142 orport=110 id=2EF3F194E34705F9E13021BAC7B394653329243A" +" ipv6=[2a12:a800:2:1:45:80:158:142]:110" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"46.38.254.168 orport=40000 id=E1E32C01926FAF7E046DF112A0385196A5125EC0" -/* nickname=Unnamed */ +"205.206.0.92 orport=9109 id=F86698F2977D6A1216215C2CCE540BC84A8508DC" +/* nickname=edmCentral0 */ /* extrainfo=0 */ /* ===== */ , -"209.233.88.131 orport=9001 id=0C8D8FF15A3B58AE4A019105C50130DD1CF8F1BF" -/* nickname=Unnamed */ +"45.80.158.249 orport=8430 id=D138382EBA7B84EF8BBC669B0A961AF758AC8FA8" +" ipv6=[2a12:a800:2:1:45:80:158:249]:8430" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"152.53.111.174 orport=9088 id=CA037B9E5174A5DCF1B3E4DB06B22E8DA76A1FE0" -/* nickname=PiratenparteiNERD */ +"194.26.192.46 orport=9100 id=EDC46D5E697DBE2C8F2F7C8D8B26EC2FCB3F2F33" +" ipv6=[2a12:a800:1:1:194:26:192:46]:9100" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"95.143.193.125 orport=443 id=01181B31BE5860C7D66DA88F88AD522C06470FD9" -/* nickname=motauri */ +"199.241.137.60 orport=9001 id=8D8DAD240CECFE9B48DC5F2C6EA20D042D5B8733" +" ipv6=[2602:ff16:6:0:1:297:0:1]:9001" +/* nickname=ac1dburn */ /* extrainfo=0 */ /* ===== */ , -"159.69.138.31 orport=9001 id=1C0736CF3744A3B87C2D2269B8BD3388C7E60552" -" ipv6=[2a01:4f8:231:1ed8:106::106]:9001" -/* nickname=FreedomFries2 */ +"94.100.6.11 orport=443 id=03E107A3663E912664F4A934DFF451262C218357" +/* nickname=Wildtwister */ /* extrainfo=0 */ /* ===== */ , -"157.245.243.70 orport=80 id=959C5AE1A34683F60C2DF7F4F48FEA24406E31E8" -/* nickname=HelpingOut */ +"62.210.181.63 orport=18256 id=6DF9B54DF49AEB5992B9AF8D4ECFA7BCC7447A8B" +" ipv6=[2001:bc8:32d7:2006::]:18256" +/* nickname=Belize */ /* extrainfo=0 */ /* ===== */ , -"45.138.16.113 orport=9000 id=DFA97DED4CE79FF6F31DAF917C2810CCE8729E9D" -" ipv6=[2a12:a800:2:1:45:138:16:113]:9000" -/* nickname=Quetzalcoatl */ +"74.208.11.136 orport=6733 id=8A67C5D1B659355698ADE012AF2C7B0EB3B3F1A9" +/* nickname=NotTheNSA */ /* extrainfo=0 */ /* ===== */ , -"62.182.84.241 orport=9001 id=2062C6FE40ED6329F02EAC8FB8DE3B682F9910EC" -/* nickname=EpicTor4 */ +"195.176.3.23 orport=443 id=BCF55F865EE6EF17E25EFEAF851BC429F190B85D" +" ipv6=[2001:620:20d0::23]:443" +/* nickname=DigiGesTor5e1 */ /* extrainfo=0 */ /* ===== */ , -"45.141.215.19 orport=143 id=0863252662246FFF6914F380711C75DC4027BD75" -" ipv6=[2a12:a800:2:1:45:141:215:19]:143" +"45.9.156.101 orport=8100 id=E492BA484812A7FED594F2852473876779617E16" +" ipv6=[2a0e:bfc7:0:3::2d83]:8100" /* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"51.75.70.246 orport=443 id=8646226690C1D4F2DDC3021F89909A26A8C32A27" -/* nickname=anonkaisx */ +"45.80.171.18 orport=9001 id=DA71126E1D0B11605533B7AD399DD5A7EC8E2F0E" +" ipv6=[2a10:3781:1f::5]:9001" +/* nickname=blackstar */ /* extrainfo=0 */ /* ===== */ , -"45.138.16.76 orport=110 id=A07B7614425A9716BB135CC502210209923659F8" -" ipv6=[2a12:a800:2:1:45:138:16:76]:110" -/* nickname=Quetzalcoatl */ +"45.138.16.230 orport=9700 id=662C083862D68475A41777EC9D9163E51FE90110" +" ipv6=[2a12:a800:2:1:45:138:16:230]:9700" +/* nickname=Aramis */ /* extrainfo=0 */ /* ===== */ , -"202.61.204.53 orport=443 id=B8B338E861F9B201A35DEB180C68053FA56C2DBE" -" ipv6=[2a03:4000:5b:e1::8]:443" -/* nickname=mullbinde8 */ +"208.72.67.116 orport=9063 id=19F03506712EBF7F1E791C11C4CA13877F9AB84B" +/* nickname=GlobalEntry */ /* extrainfo=0 */ /* ===== */ , -"114.23.164.80 orport=9001 id=CB81BCFD44FC142616BB5983648BD8AF01930789" -/* nickname=ss23voyager */ +"64.65.1.103 orport=443 id=6562CB938FE7B45629B8AEE4C8478D02A27D4492" +/* nickname=youngdolph */ /* extrainfo=0 */ /* ===== */ , -"194.147.140.107 orport=443 id=D3433B2F0860FEFBEC1677E67F8110F5655A4E86" -" ipv6=[2001:67c:440:f887:194:147:140:107]:443" -/* nickname=tor107 */ +"135.181.67.210 orport=443 id=DC7E7D9AB7AD52F03B856E6DC278E9D92BF19B33" +" ipv6=[2a01:4f9:4b:4e97::6666]:443" +/* nickname=s6tor2 */ /* extrainfo=0 */ /* ===== */ , -"140.78.100.14 orport=5443 id=C1CA4E603F152E8C86E864F4FBF1162A3BFDF587" -/* nickname=INSRelay14at5443 */ +"96.9.98.188 orport=443 id=E68789BC34CFC5B932E827C463E104ECFB9FA060" +/* nickname=liltjay */ /* extrainfo=0 */ /* ===== */ , -"95.23.252.197 orport=9001 id=16530D8CCD6A7C2C13564A573E9B23CE1A4AD24F" -/* nickname=mypirelay */ +"185.73.240.205 orport=443 id=A60AFA6FFB2EEB8E4A4C531FBA6A78AF586AACB7" +/* nickname=adlon */ /* extrainfo=0 */ /* ===== */ , -"88.80.26.2 orport=9001 id=A041465163D91E5F11B230F089784EB6CEF653CB" -" ipv6=[2a00:16b0:1:243::7012:3117]:9001" -/* nickname=PRQseTORexit2 */ +"181.215.45.194 orport=9001 id=426E5509BEA3CEB670EAB6789872B729C178A7BE" +" ipv6=[2a0e:b107:1ef0:0:181:215:45:194]:9001" +/* nickname=relaytorparacba */ /* extrainfo=0 */ /* ===== */ , -"118.27.12.40 orport=9001 id=2A0AC8016D9A0297BE4CCA1C575DFCEC9866E681" -" ipv6=[2400:8500:1801:406:118:27:12:40]:9001" -/* nickname=SaruTorHebi */ +"84.167.246.41 orport=9002 id=BCB8813996025205A8BDDED17DF0372367207205" +/* nickname=crmh */ /* extrainfo=0 */ /* ===== */ , -"151.189.64.113 orport=9001 id=A29D2A78A8A954819E220CEFBEBCE95D2FCFA54D" -/* nickname=RoteServerPaul */ +"194.26.192.186 orport=9300 id=53A6473ACE36671C79AB985D3237C179E850FA62" +" ipv6=[2a12:a800:1:1:194:26:192:186]:9300" +/* nickname=prsv */ /* extrainfo=0 */ /* ===== */ , -"23.92.34.43 orport=443 id=0E947CA987F0D5890E2374556483D59148877C30" -/* nickname=JimmyHardingMi10046 */ +"185.82.127.213 orport=443 id=24E9CFAE081B16E87B490C596C18B00EE6FF8413" +/* nickname=se3andersio */ /* extrainfo=0 */ /* ===== */ , -"94.23.76.52 orport=443 id=DB1629B59707F744A0C7933E56B6802786FFC317" -/* nickname=deimos */ +"5.254.118.191 orport=9001 id=A7AA32CA10E1BEDA1E976A659FD96CA99C2D86FE" +/* nickname=Dominos */ /* extrainfo=0 */ /* ===== */ , -"95.141.83.155 orport=443 id=F148A022E5E2BAD006E29C82C8D47C047A29958F" -" ipv6=[2a02:f58:4:300:216:3eff:fec2:a1f9]:443" -/* nickname=Unnamed */ +"192.42.116.65 orport=443 id=0055DB090820D7C08999EC1598FD6EA6365861AD" +" ipv6=[2001:67c:e60:c0c:192:42:116:65]:443" +/* nickname=NTH65R1 */ /* extrainfo=0 */ /* ===== */ , -"142.44.227.24 orport=9191 id=310229E3B5C106CE63F98C24F91F56370647BBB0" -/* nickname=iamphoenix */ +"185.233.100.23 orport=19001 id=4A39E7D2C121F664CFD9B5DF80CE9E70BB8B3C16" +" ipv6=[2a0c:e300:b:b::b]:19001" +/* nickname=elenagb4 */ /* extrainfo=0 */ /* ===== */ , -"185.220.101.39 orport=10039 id=7ABED1F6664D1153F1402838D3B32AF6F2CABE17" -" ipv6=[2a0b:f4c2:2::39]:10039" -/* nickname=ForPrivacyNET */ +"45.80.158.167 orport=7100 id=09257AB36470E686491710153FF9412ACC53F2A0" +" ipv6=[2a12:a800:2:1:45:80:158:167]:7100" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"23.19.225.69 orport=443 id=06BC159DAA7EB0DB626B2E1B6EFA1E9F0907CD8B" -/* nickname=Unnamed */ +"45.80.158.93 orport=8430 id=F5A47B1E8397139628FA424C1C7A560232E35EB4" +" ipv6=[2a12:a800:2:1:45:80:158:93]:8430" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"37.48.120.47 orport=110 id=4D9AF7BB47633B2B7B72D529562BFDA47A5821C9" -/* nickname=Taco */ +"212.47.233.86 orport=9001 id=B4CAFD9CBFB34EC5DAAC146920DC7DFAFE91EA20" +" ipv6=[2001:bc8:710:5bcb:dc00:ff:fe5e:e8b5]:9001" +/* nickname=netimanmu */ /* extrainfo=0 */ /* ===== */ , -"68.71.25.194 orport=9011 id=413E3AE5AB2371689AE5F4E1A32029037ACDFD22" -/* nickname=GunOil */ +"23.191.200.7 orport=443 id=5BC542BEC38E8D373D21C6A79CC9348DC28BD62C" +/* nickname=UnredactedRadack */ /* extrainfo=0 */ /* ===== */ , -"185.107.57.66 orport=443 id=90C9567666C9E4B1C0CB7E50968AC2752AA6D088" -/* nickname=wix */ +"23.108.55.71 orport=443 id=DF885E50651903A212EE519BE5A58397AD2E0975" +/* nickname=hamburger */ /* extrainfo=0 */ /* ===== */ , -"116.203.135.195 orport=9001 id=DA3FD24EDEA501C7133307CA73E991AC5B1D76BF" -" ipv6=[2a01:4f8:1c1e:68bd::1]:9001" -/* nickname=Eigentor */ +"86.54.28.49 orport=443 id=98CDDAF76419C5DBCBCF512D87E3F99BA5F22770" +/* nickname=OMICRON */ /* extrainfo=0 */ /* ===== */ , -"89.58.34.53 orport=9001 id=01B8F18C11CE2877E8190FA2C81808CD087515C0" -" ipv6=[2a03:4000:64:fe8:c853:14ff:fe86:7a3d]:9001" -/* nickname=root1Moh */ +"62.210.122.182 orport=9201 id=B91A1EB30E66D52026EFCD1E96BFC0E966C83E6D" +" ipv6=[2001:bc8:32d7:10b::f1fa:9201]:9201" +/* nickname=Assange008fr2 */ /* extrainfo=0 */ /* ===== */ , -"148.251.151.125 orport=9001 id=97E4BAB582717350E6FF6160899FA9B665C834E3" -" ipv6=[2a01:4f8:210:504b::3]:9001" -/* nickname=LSTorRelay01 */ +"74.140.253.100 orport=9001 id=F84C674E4932768107D6460318CC0F73EF8CF493" +/* nickname=DisrodRelay */ /* extrainfo=0 */ /* ===== */ , -"79.141.165.172 orport=9001 id=D6EDD332AC04B1D1E8FEFB3F32F4C050CDB3A95B" -/* nickname=DELIGHT */ +"194.180.191.93 orport=9001 id=677347441FDD2AEA22BD364A7174D277E929B255" +/* nickname=abnormalbonus */ /* extrainfo=0 */ /* ===== */ , -"65.109.30.253 orport=28713 id=AEF02E45E067CC18559ED5E851859E3AAB7AAA84" -/* nickname=NowhereDOTmoe */ +"64.65.2.12 orport=443 id=8D55E78059CB694ABD69DEED64D444862B79D8E1" +/* nickname=hitboy */ /* extrainfo=0 */ /* ===== */ , -"139.99.134.168 orport=443 id=0F53B4B16768A8A18B838103DD500068C4D656EB" -/* nickname=whynot1 */ +"64.65.1.20 orport=443 id=A69AAF75702AB9041A3EDA1918F930377E13F39D" +/* nickname=statquo */ /* extrainfo=0 */ /* ===== */ , -"192.121.108.237 orport=9001 id=A9C6FEA058C3E53ECDA61E8FDAD0F940718DE8CE" -/* nickname=HjelmEnterprises02 */ +"218.236.76.26 orport=9002 id=0A30E1467618B1AC167D012C9718C57B4E5F68F3" +/* nickname=Unnamed */ /* extrainfo=0 */ /* ===== */ , -"150.230.20.28 orport=9001 id=054AF5AE5DA4AA0B81D7155542AF204252CB6D61" -" ipv6=[2603:c022:c002:b0e:f620:461d:1cc1:fa75]:9001" -/* nickname=Plusle */ +"96.9.98.27 orport=443 id=C6426F3974070BEBB6F4E019EBC96F4A2A3C8DB7" +/* nickname=yungpinch */ /* extrainfo=0 */ /* ===== */ , -"82.197.160.67 orport=9001 id=B8F9E02E70A2A32E6EF1C04FC9F9A7B87435E50A" -/* nickname=haustre1 */ +"176.65.148.3 orport=443 id=7FF8F83DD10D3E685B6846D5C32593C1B62A9945" +" ipv6=[2a05:b0c7:655b::1]:443" +/* nickname=nix */ /* extrainfo=0 */ /* ===== */ , -"152.70.140.84 orport=9001 id=02B4B5B92EE60D5317A0DB301175737AB8F1718A" -/* nickname=Shado */ +"207.90.194.2 orport=443 id=A39D10B59C0614DFFE296DC2C55F7C4C8557D485" +" ipv6=[2602:ffd5:1:29c::1]:443" +/* nickname=fluffypancakes002ca */ /* extrainfo=0 */ /* ===== */ , -"213.165.86.67 orport=14960 id=CAD9DF79A3B4C0A23BBEECE5E546D7FD2016459E" -" ipv6=[2a01:239:331:7200::1]:14960" -/* nickname=theshowmustgoon */ +"185.220.101.203 orport=443 id=B7E9849D446FC57D4BDED937B8E17F3AACE1FA06" +" ipv6=[2a0b:f4c2:2:1::203]:443" +/* nickname=ForPrivacyNET */ /* extrainfo=0 */ /* ===== */ , -"185.119.117.229 orport=443 id=629301C063FC047171C8A0F1520A9D7CF60308EC" -" ipv6=[2a00:63c1:13:229:fa53:5051:8c88:ff1e]:443" -/* nickname=ekanu */ +"64.65.2.35 orport=443 id=8E663773B6489347EE34C6D3FFCFD9D6FC80A2DE" +/* nickname=timbaland */ /* extrainfo=0 */ /* ===== */ , -"45.134.91.219 orport=9001 id=8C88990D44239803692CFAA68DDC74FEB5E6E9C7" -" ipv6=[2a0c:9a40:2805:1::198f]:9001" -/* nickname=droidtakeover */ +"64.65.62.20 orport=443 id=A92C33AE18D64EEC719FAF3038FD8F52462BA3FD" +/* nickname=hdbearfaced */ /* extrainfo=0 */ /* ===== */ , -"45.11.59.28 orport=443 id=2FF8FFB28EAA635E291D623E03F231AC265F28F9" -/* nickname=AnneMarie */ +"74.123.98.18 orport=443 id=A2C85DB6C3D64D7178D24848FD8A0E59347F2E6D" +/* nickname=tournament */ /* extrainfo=0 */ /* ===== */ , -"192.121.44.26 orport=9001 id=5975858B6A1F37CCC96026B946EACF08E1772D0E" -/* nickname=Playstar01 */ +"77.68.20.86 orport=443 id=07C17931AE2E17F95681FA2A91C7F7CDB068BF48" +" ipv6=[2a00:da00:f412:c100::1]:443" +/* nickname=SidNYGiants */ /* extrainfo=0 */ /* ===== */ , -"185.220.101.200 orport=8443 id=674F66D7D8C6F0DF9997B3C9423AA153C988FE77" -" ipv6=[2a0b:f4c2:2:1::200]:8443" -/* nickname=ForPrivacyNET */ +"15.204.103.3 orport=9030 id=4D4748577DC4F963A9BACF51E1D49B86F12CE23E" +" ipv6=[2604:2dc0:200:2903::]:9030" +/* nickname=Solsticist */ /* extrainfo=0 */ /* ===== */ , -"66.78.40.183 orport=9300 id=0E1AA3CDB938089905F4DD651F6810C7EBAD283F" -/* nickname=mursec */ +"51.15.243.22 orport=443 id=1C7D71A2581DE79C5CFC4ED1FF75D5BE30F01BB7" +/* nickname=BabyOnion */ /* extrainfo=0 */ /* ===== */ , -"188.165.222.73 orport=443 id=AEF6C1FBA0FC16F4931638BF065085B974D3E90F" -/* nickname=MidwayStation */ +"171.25.193.234 orport=80 id=CF1C1804C33CD69D8A75587FABC63D5D0E2980FA" +" ipv6=[2001:67c:289c:2::234]:80" +/* nickname=DFRI10 */ /* extrainfo=0 */ /* ===== */ , -"185.220.101.206 orport=8443 id=ADF0D51946DA3294C1F242B0ACADC91FF5F058EF" -" ipv6=[2a0b:f4c2:2:1::206]:8443" -/* nickname=ForPrivacyNET */ +"188.214.132.18 orport=9001 id=EA9E042A05E851076A657639CD0C84D8DA86A76F" +/* nickname=blockaide */ /* extrainfo=0 */ /* ===== */ , -"128.31.0.13 orport=443 id=A53C46F5B157DD83366D45A8E99A244934A14C46" -/* nickname=csailmitexit */ +"185.153.182.11 orport=9001 id=BEBE82BEAB014983F55DD4CA94CE33E3751B1FDA" +/* nickname=Assange044tr */ /* extrainfo=0 */ /* ===== */ , -"140.238.145.127 orport=9001 id=9F7A69E381CA06322EB44F81DE7928BF7BDD60C0" -/* nickname=tendies1 */ +"178.236.254.48 orport=9000 id=121212BF2F3ED5FA26B65CB376394F4EA322FEBE" +" ipv6=[2a0b:4141:820:138::2]:9000" +/* nickname=prsv */ /* extrainfo=0 */ /* ===== */ , -"185.220.101.138 orport=11138 id=3158BE2413AC6A8F0BC3EC343BB056F6D24F2E53" -" ipv6=[2a0b:f4c2:1::138]:11138" -/* nickname=relayon1138 */ +"86.14.169.71 orport=443 id=417AA3C8D226DDD79A8047D7F217B21D9C63C21F" +" ipv6=[2001:470:681e::dead:c0de]:443" +/* nickname=sudokill */ /* extrainfo=0 */ /* ===== */ , -"185.207.125.14 orport=443 id=58D4282355F0149BD9D8230AAF803CE3EA4C00CA" -" ipv6=[2a0d:8144:0:120::]:443" -/* nickname=AntonPann4 */ +"89.58.17.228 orport=46856 id=593A4431DA2E315883406AECE1D1188E02F23D8F" +" ipv6=[2a0a:4cc0:0:f0a:a45c:7aff:fe13:2781]:46856" +/* nickname=klarheit */ /* extrainfo=0 */ /* ===== */ , -"45.138.16.107 orport=9100 id=D88B5B35EF4D5EF11F5B670C364F812D0349B8DB" -" ipv6=[2a12:a800:2:1:45:138:16:107]:9100" -/* nickname=Quetzalcoatl */ +"196.200.160.95 orport=9001 id=483E50E35E3CFFA1B69F1AC6B452053AEB7C9581" +" ipv6=[2001:4310:f1::95]:9001" +/* nickname=toky0 */ /* extrainfo=0 */ /* ===== */ , -"198.50.223.16 orport=443 id=896364B7996F5DFBA0E15D1A2E06D0B98B555DD6" -" ipv6=[2607:5300:203:7ac5:198:50:223:16]:443" -/* nickname=blackmamba */ +"147.189.174.139 orport=9001 id=8F229BC977B322E10826E1605386799E5273ED73" +/* nickname=zgato */ /* extrainfo=0 */ /* ===== */ , -"213.144.135.21 orport=443 id=BB5FAE50BCE5B13C810CD17A931A0498E4681D41" -" ipv6=[2a02:168:6a16:1130::32:101]:443" -/* nickname=YoYuD1N01NoExit */ +"185.244.194.156 orport=4711 id=B13BF9FB86663B2D587611B5F3369873919AC54F" +" ipv6=[2a03:4000:27:71a:1853:7aff:feaf:449b]:4711" +/* nickname=makeitfoss */ /* extrainfo=0 */ /* ===== */ , -"195.90.217.102 orport=443 id=B3CA62427654C23F99DA9100D7B0916E6E0FE365" -/* nickname=FatalFurry */ +"205.185.113.180 orport=9001 id=80914004BD527CE984A1576CA63AAA77944D9D2B" +" ipv6=[2605:6400:20:482:3920:1829:1839:1293]:9001" +/* nickname=anonymityiscool */ /* extrainfo=0 */ /* ===== */ , -"65.109.67.182 orport=8080 id=C4AD03D01F7A6C29045B9F1034237B40D1384E66" -" ipv6=[2a01:4f9:5a:442b::4]:8080" -/* nickname=Enkidu4 */ +"140.78.100.37 orport=8443 id=CFB535715442BC0E9F6AF224A794BBFA02D0B343" +/* nickname=INSRelay37at8443 */ /* extrainfo=0 */ /* ===== */ , -"146.70.222.42 orport=443 id=EDDD1EE1E5EF2C35C70C8FED5A52EF46E08597AF" -/* nickname=Unnamed */ +"209.250.2.254 orport=443 id=205ED2C309999F0F18767A1ECCD384B580070BA9" +" ipv6=[2001:470:1f19:c2::9090:1]:9090" +/* nickname=RazorsEdge */ /* extrainfo=0 */ /* ===== */ , -"45.141.215.88 orport=9000 id=1E3C197C8C922128FF049856E0536FF9CB4E5E8C" -" ipv6=[2a12:a800:2:1:45:141:215:88]:9000" +"45.9.156.193 orport=7430 id=7C9FC7C99D7F83980E621BA8D4E0D40FCE53104F" +" ipv6=[2a0e:bfc7::216:3cff:feae:41de]:7430" /* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"144.6.189.17 orport=9000 id=627D47EC57C18B4CF3E135B76177C73BE8F4B965" -" ipv6=[2403:5804:8b55:3:0:73:636f:6d6f]:9000" -/* nickname=SCOMO */ +"195.88.75.18 orport=9001 id=3F1B13B101DB4D043D0DA18272B8646D3132EE47" +/* nickname=rarelotus */ /* extrainfo=0 */ /* ===== */ , -"94.142.241.41 orport=443 id=8E84C81FA99A70AFD2751B761435D2A301CFFBAB" -/* nickname=NTH100R4 */ +"107.174.64.206 orport=9954 id=34C5ECB828A275A472F78CE0BBC0884E17E14B1D" +/* nickname=opencommunity */ /* extrainfo=0 */ /* ===== */ , -"185.182.193.16 orport=8443 id=DC0B2CF7EFBE640DF3D1615EB8FE50E82FB53B45" -/* nickname=serv01 */ +"64.65.1.72 orport=443 id=6FE1A22BAC0635BA510E2EFE1249D7AA4BECBE67" +/* nickname=xalisoflow */ /* extrainfo=0 */ /* ===== */ , -"209.182.200.18 orport=443 id=D80A169627F8819A8814A134A6CDA9B6E553CF42" -/* nickname=Unnamed */ +"104.167.241.4 orport=443 id=4625F385CA5364CDD63C791893973B0CAD49C4E0" +" ipv6=[2602:fccf:100:3::14]:9001" +/* nickname=HoustonTexas4Torcom */ /* extrainfo=0 */ /* ===== */ , -"209.141.45.81 orport=5060 id=1E89F4CDEE77841C380A4FBB82FB997219867424" -" ipv6=[2605:6400:20:c26:5163:253e:1ef6:d896]:5060" -/* nickname=hogman5 */ +"64.65.0.33 orport=443 id=7EA091DF4CE4256ED35DC113D4921867CBF03A0E" +/* nickname=megaran */ /* extrainfo=0 */ /* ===== */ , -"45.141.215.81 orport=9000 id=42708A12892506EBCD881BCB3648E78D93DC2781" -" ipv6=[2a12:a800:2:1:45:141:215:81]:9000" +"45.141.215.200 orport=7430 id=4BDF25CD6E8482C0E835F6A70918540F4FC4CF22" +" ipv6=[2a12:a800:2:1:45:141:215:200]:7430" /* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"185.220.101.202 orport=8443 id=9A338F384C5FD3A3604E3250CCF5F5F7629D7717" -" ipv6=[2a0b:f4c2:2:1::202]:8443" -/* nickname=ForPrivacyNET */ +"96.9.98.58 orport=443 id=843E20D60EB7EF118FE8F4F4ACABD1AACE59E9B3" +/* nickname=smokepurpp */ /* extrainfo=0 */ /* ===== */ , -"94.23.88.117 orport=443 id=D870744F618F20F3A63592B4F9B0BB919FC1BED0" -/* nickname=Unnamed */ +"45.11.248.196 orport=9001 id=60DC7DDDCD659C47D4644EDF97E2ACC3C6B18EEB" +" ipv6=[2a00:6340:2043:5000::1]:9001" +/* nickname=surveyor */ /* extrainfo=0 */ /* ===== */ , -"193.182.111.133 orport=443 id=F30B55F9F9140A9D47CF6AC775E7A4CB1BD478E1" -" ipv6=[2a03:8600::a6]:443" -/* nickname=ParadiseTorRelay6 */ +"37.187.122.8 orport=9001 id=221E976B546E60048A01950250399B8534D4E4B7" +" ipv6=[2001:41d0:a:f308::1]:9001" +/* nickname=malechick */ /* extrainfo=0 */ /* ===== */ , -"80.67.167.81 orport=19008 id=16D3252B519861248FDEABE05A6F3B97BC510557" -" ipv6=[2a0e:e701:1198::1]:19008" -/* nickname=arecoque8 */ +"80.94.92.99 orport=9200 id=D1968B63E1105F5E71CC28026687F3C86A46C46E" +/* nickname=prsv */ /* extrainfo=0 */ /* ===== */ , -"45.80.158.205 orport=9000 id=E84F41FA1D1FA303FD7A99A35E50ACEF4269868C" -" ipv6=[2a12:a800:2:1:45:80:158:205]:9000" -/* nickname=Quetzalcoatl */ +"185.4.134.104 orport=9001 id=C6E3910CBADCA6D2D7E932AB31A038EDD6A6FB79" +" ipv6=[2a02:c500:2:110::8709:9001]:9001" +/* nickname=Assange023gr */ /* extrainfo=0 */ /* ===== */ , -"198.251.88.18 orport=8080 id=8A5ACFC8FDF21A3D836DB7ECEBA6538392F496E6" -" ipv6=[2605:6400:30:f174:42:42:42:42]:443" -/* nickname=Polyphemus16 */ +"164.215.103.126 orport=9001 id=2144EC311E714F30648F2B62546E2CA28FDBD36B" +/* nickname=caseyjones */ /* extrainfo=0 */ /* ===== */ , -"15.204.140.9 orport=8443 id=3FB88013FAC7AB8F479F33F5B484BE9F444330C3" -/* nickname=Parzival */ +"217.123.118.44 orport=9001 id=047DFF9DBA6A7DB666626F7F4560A1D7B1135F73" +/* nickname=VegetaSSJ */ /* extrainfo=0 */ /* ===== */ , -"84.252.120.63 orport=443 id=873914828C1161F02771F51AC7D97456317FC041" -" ipv6=[2a0c:2500:571:6bf:f10d:eb5:1b24:f5d1]:443" -/* nickname=SLAVAUKRAINI */ +"64.65.3.35 orport=443 id=5BCA9F58CA3C8C130998C8F853921DD56CEF0C2C" +/* nickname=youngma */ /* extrainfo=0 */ /* ===== */ , -"185.40.4.150 orport=8166 id=3287F79D9C1687BF7F3A9D140369CA64D2FD111B" -/* nickname=terNOicebeer17 */ +"38.29.158.193 orport=9001 id=269885C61FD6CFCC54BD86B88A82565956A42F55" +/* nickname=fr33domNod3 */ /* extrainfo=0 */ /* ===== */ , -"77.174.62.158 orport=9001 id=752AA93C16DC039D86F88C8CAC5AC43CA3A87DDD" -" ipv6=[2a02:a468:8d92:1:1e86:bff:fe20:2c8]:9001" -/* nickname=op2 */ +"198.28.165.248 orport=36325 id=A526EA0B6BB1C7B2B7163E834963FC1884A6914E" +/* nickname=vici */ /* extrainfo=0 */ /* ===== */ , -"37.120.171.64 orport=9002 id=47D55C9BD170C948961EF1B6C5D1AEB4CF8F7D06" -" ipv6=[2a03:4000:6:537c::4]:9002" -/* nickname=Unnamed */ +"185.194.143.87 orport=35897 id=54625FCF74D8311F3175349A1F879A0A298D5CA8" +" ipv6=[2a03:4000:1c:555::11e8]:43741" +/* nickname=TorNode05 */ /* extrainfo=0 */ /* ===== */ , -"158.101.203.38 orport=9001 id=145223A4F761DD9F0E14DCDF5120FED4F998FDC6" -" ipv6=[2603:c022:c002:b0e:df68:94b3:52b1:5f2c]:9001" -/* nickname=Minun */ +"23.141.40.7 orport=443 id=375DCBB2DBD94E5263BC0C015F0C9E756669617E" +" ipv6=[2620:b0:2000:102::7]:443" +/* nickname=nitrogen */ /* extrainfo=0 */ /* ===== */ , -"87.236.195.216 orport=1000 id=50161FF42B11B87C4CDD210CF9CB490A7B088DBB" -/* nickname=Perseverance */ +"152.53.252.155 orport=443 id=D19E920B886D664E21EB88AF7D955CA4FC570181" +" ipv6=[2a0a:4cc0:c0:bbbd:4660:c905:736b:bee8]:443" +/* nickname=jilfrg60 */ /* extrainfo=0 */ /* ===== */ , -"148.251.85.195 orport=9030 id=77A3ADC5D455778B53C2803761916DFB7DA0A790" -" ipv6=[2a01:4f8:202:6096::2]:9030" -/* nickname=redvader */ +"74.108.36.251 orport=9001 id=192B3306D8A064510CE6363D5AFFB563E789D246" +/* nickname=LittleIsland */ /* extrainfo=0 */ /* ===== */ , -"51.81.155.229 orport=8443 id=FD10A98858ED6B883D0C46157081C12C386C9167" -/* nickname=bludger2 */ +"5.45.99.251 orport=8080 id=75C0B7A2650BD317CE0FF4EE37DEA093AAD9019B" +" ipv6=[2a03:4000:5:b1:14bb:a9ff:fe0f:70c3]:8080" +/* nickname=northerndownpour */ /* extrainfo=0 */ /* ===== */ , -"95.214.53.96 orport=8446 id=C549A2169DAF079B61520C29E567589FE3F8E606" -" ipv6=[2a03:cfc0:8000:7::5fd6:3560]:8446" -/* nickname=bauruine */ +"5.180.82.224 orport=443 id=BA36742C1FBA693619E085899AC6970C5D3F2A53" +/* nickname=khajiitthief */ /* extrainfo=0 */ /* ===== */ , -"140.78.100.39 orport=5443 id=B97715C8A1EE72679C74480F301B11AC015B4C54" -/* nickname=INSRelay39at5443 */ +"91.92.109.23 orport=443 id=81D4A9FB174118AA4809B4EE209982FFF215E8A9" +/* nickname=whatscrackin */ /* extrainfo=0 */ /* ===== */ , -"70.39.91.99 orport=81 id=315D1201A80DCA0AB6D5BA6514F9152FDEFEA0E0" -/* nickname=elites4 */ +"192.34.87.86 orport=9001 id=CBC8D277C35BCE9512BA45479CF8141FC6A2CD73" +/* nickname=iamthatdude */ /* extrainfo=0 */ /* ===== */ , -"217.160.24.47 orport=9001 id=45431BF8AB66C673942C1E344BB520625CE5F817" -" ipv6=[2a01:239:27f:4400::1]:9001" -/* nickname=observatory123 */ +"198.23.133.146 orport=9001 id=B00A2DE75DEB8ABB3058290CE311A3D9D096797A" +/* nickname=DebbieDoesTor2023 */ /* extrainfo=0 */ /* ===== */ , -"194.5.101.253 orport=443 id=62CDBF67AD8C00076CEA20C2BC56A8CCBC2C5D0A" -/* nickname=nrdtrn01 */ +"92.205.161.164 orport=80 id=65369D044C659CD299E35763914FFD0FC9AD4509" +" ipv6=[2a00:1169:11c:3e00::]:443" +/* nickname=Charybdis5 */ /* extrainfo=0 */ /* ===== */ , -"5.254.118.189 orport=9001 id=234B06E4DA915D527C897E21FD1E9F08012E2962" -/* nickname=Pizzahut */ +"24.125.17.222 orport=443 id=EB044ED4110BA4A6D546992B457DFD13C52B96E5" +/* nickname=mammoth */ /* extrainfo=0 */ /* ===== */ , -"72.235.129.116 orport=4443 id=77AC367C04CBA86B93DAA29B7CB3DD12CD363F06" -/* nickname=hnlexit2 */ +"193.189.100.197 orport=445 id=3C518040CA63BB9EA6B2BE3F514B7168DCC72A74" +" ipv6=[2a0f:df00:0:255::197]:445" +/* nickname=TORKeFFORG30 */ /* extrainfo=0 */ /* ===== */ , -"45.141.215.169 orport=9000 id=552C2E2AFDD1B740A38CA9768C51EC011B2AF701" -" ipv6=[2a12:a800:2:1:45:141:215:169]:9000" -/* nickname=Quetzalcoatl */ +"89.106.71.126 orport=9001 id=C588F709A5D9CF37358E456003645CDC74BC8B3C" +" ipv6=[2a02:2fc0:11::71:126]:9001" +/* nickname=DediZoneRelay */ /* extrainfo=0 */ /* ===== */ , -"57.129.44.38 orport=9200 id=1B0AAE2012DB8E364A42739906249E1E8959A216" -/* nickname=prsv */ +"23.137.248.69 orport=443 id=A24CB2FAB0B4CC1F1965CC7FA332AB1184617DDA" +" ipv6=[2602:fc24:11:16f9::1]:443" +/* nickname=AntonPann8 */ /* extrainfo=0 */ /* ===== */ , -"200.122.181.2 orport=443 id=7D33FC2D047493C6A514F5A4C1D70FCA54EA55DD" -/* nickname=Michelangelo */ +"217.154.188.247 orport=443 id=8B8A8328539BF34221C1F136D6EAA48EFCAD379D" +" ipv6=[2001:ba0:215:f000::1]:443" +/* nickname=0x011 */ /* extrainfo=0 */ /* ===== */ , -"116.12.180.234 orport=443 id=98A6022D39DD25902D7728B65BE28E5557F5B914" -/* nickname=maplefire */ +"51.15.96.2 orport=443 id=56344DEE34D3343090D00AD88CE2D58B50712C81" +" ipv6=[2001:bc8:1640:777:dc00:ff:fe12:d075]:443" +/* nickname=gh5d4h56s468r784s32 */ /* extrainfo=0 */ /* ===== */ , -"74.215.154.5 orport=9001 id=74B065244F5B429E55DA072D8C0D1C787167AAC2" -" ipv6=[2600:2b00:9358:2004:aab8:e0ff:fe00:87f3]:9001" -/* nickname=evequefou */ +"185.244.192.184 orport=9100 id=3AD0E099EA0F64B6202BEE3B737A9FE5D554A3CC" +" ipv6=[2a03:4000:27:36:c813:6dff:fe0e:b93e]:9100" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"92.60.37.143 orport=9001 id=F50CF02A0E6A9D9B25F7EB220FC26F7BD1B74999" -" ipv6=[2a03:4000:33:255:2895:5dff:fe24:437d]:9001" -/* nickname=flowjob02 */ +"23.129.64.140 orport=443 id=C98CD99E2BF5F1D7EFA5ED90646AF809CE8F75DF" +" ipv6=[2620:18c:0:192::e0:140]:443" +/* nickname=kiriakou */ /* extrainfo=0 */ /* ===== */ , -"185.162.249.126 orport=9001 id=DB5DE88B4914F60CDEEF581ECCA8DEA59EF26A90" -" ipv6=[2a03:4000:1a:6f8:98f0:87ff:fe6a:29af]:9001" -/* nickname=Piratenpartei06 */ +"64.65.2.44 orport=443 id=5CA1EBAC7D56273D719B3405DC361DCFEACC4863" +/* nickname=statikselektah */ /* extrainfo=0 */ /* ===== */ , -"45.141.215.28 orport=9100 id=1D764756B76BCD821D57242649DE50F4C872F4EF" -" ipv6=[2a12:a800:2:1:45:141:215:28]:9100" -/* nickname=Aramis */ +"185.255.122.39 orport=443 id=406A030C4A33800DA8E8CDCA72DAFC446A3787AC" +/* nickname=Unnamed */ /* extrainfo=0 */ /* ===== */ , -"185.241.208.245 orport=9000 id=C3F9572611FF1084615219D8CE3AE6848C1DCCAD" -/* nickname=RDPdotSH */ +"74.215.154.5 orport=9003 id=1D4F6F26E34E2C571F25E93605EDBC95626760FD" +" ipv6=[2600:2b00:939e:710d:aab8:e0ff:fe00:87f2]:9003" +/* nickname=evequefou3 */ /* extrainfo=0 */ /* ===== */ , -"78.142.18.219 orport=9444 id=3EF2D316BC791FF4B9460B41A6C31EC44C525619" -/* nickname=bauruine */ +"144.126.133.74 orport=143 id=ACB30ED82CA61B49E38E5969505D7E2F29897AA1" +" ipv6=[2605:a140:2262:7686::1]:143" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"178.248.249.172 orport=9050 id=F1CC14C298442FAFF00762BA4339ECBED1AC0F92" -/* nickname=msbobo4 */ +"185.181.60.181 orport=443 id=335E993222204F6B4817134506494A6441DEFB6B" +" ipv6=[2a03:94e0:ffff:185:181:60:0:181]:443" +/* nickname=DowntimePatrol1 */ /* extrainfo=0 */ /* ===== */ , -"193.63.58.76 orport=9001 id=462C4C97170DE94F251A46F4C741032864AD1BFB" -/* nickname=gnosti */ +"185.42.170.203 orport=443 id=5D263037FC175596B3A344132B0B755EB8FB1D1C" +/* nickname=anduinExit01 */ /* extrainfo=0 */ /* ===== */ , -"45.138.16.76 orport=7430 id=601021EEAF3207505D67DEB77F40A9914A9B8856" -" ipv6=[2a12:a800:2:1:45:138:16:76]:7430" -/* nickname=Quetzalcoatl */ +"77.20.3.30 orport=433 id=781817A50379EE962CC031A7C059791CEF11ACC4" +/* nickname=DocTor */ /* extrainfo=0 */ /* ===== */ , -"192.129.10.18 orport=443 id=828DF913997A261E05F894F11CD39573356B368E" -" ipv6=[2001:638:a004:4111:192:129:10:18]:443" -/* nickname=FAUtor */ +"203.55.81.1 orport=443 id=5D9D80195162D7D77506EAF768F00F70A51CD191" +/* nickname=lunar1 */ /* extrainfo=0 */ /* ===== */ , -"73.61.87.62 orport=9001 id=1FFDC7F90DBCDE587C3524FB3FBB50B818565357" -/* nickname=Chrysophylax */ +"5.135.68.65 orport=443 id=1580298405E54F02FF6F66637C3FC7077D363CDC" +" ipv6=[2001:41d0:303:9d44::1]:443" +/* nickname=Scalpay */ /* extrainfo=0 */ /* ===== */ , -"195.90.200.83 orport=9001 id=8639EC2D472AEC280B11288ADADBCC9A6711EC1B" -/* nickname=TorRelayFL */ +"45.138.16.164 orport=8100 id=2FDB0E08C563AB5D225FDBD553D117C96D1160ED" +" ipv6=[2a12:a800:2:1:45:138:16:164]:8100" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"192.42.116.211 orport=9001 id=24896D19C6DCF62050A1A46EE3C2C10DA125A867" -" ipv6=[2001:67c:6ec:203:192:42:116:211]:9001" -/* nickname=NTH14R2 */ +"37.187.149.125 orport=9001 id=46BACCCE4BC3CAA63D2FE770DA2AE3CF401B9CF0" +" ipv6=[2001:41d0:a:557d::1]:9001" +/* nickname=SORgaming */ /* extrainfo=0 */ /* ===== */ , -"46.149.125.9 orport=9001 id=21E86043B0AA1DD258F7801BEE21D2227844EC79" -" ipv6=[2001:470:6e:f0::2]:9001" -/* nickname=hpproSW3 */ +"64.65.1.210 orport=443 id=08CBCC075BD2511E989823846F8F9505380F2740" +/* nickname=shotgunshane */ /* extrainfo=0 */ /* ===== */ , -"162.247.74.202 orport=443 id=47E49319DD67784F1E65B5793371BE467365979E" -/* nickname=CalyxInstitute15 */ +"64.65.2.26 orport=443 id=556C9A64ED5489352B402ABB784B70CAE243D37C" +/* nickname=marleymarl */ /* extrainfo=0 */ /* ===== */ , -"116.203.17.238 orport=9001 id=28090710ABE433A47021F22208B3EC245A912900" -/* nickname=dismail */ +"96.9.98.88 orport=443 id=E237E9F386F14456E99EED36B1FAC4F9F77B0F80" +/* nickname=stormyz */ /* extrainfo=0 */ /* ===== */ , -"57.129.5.162 orport=443 id=FE05FEFAE7AED4F3D05C3A308999EA2113EC3383" -" ipv6=[2001:41d0:701:1100::cb3]:443" -/* nickname=mitFineRelee */ +"64.65.62.25 orport=443 id=722C8F1B5ADA4C274F36D7DD8A32DE7F3298242A" +/* nickname=lilwayne1 */ /* extrainfo=0 */ /* ===== */ , -"172.81.131.87 orport=443 id=1776B82878E571E3969A6A7F7EA140A8853F11DB" -" ipv6=[2605:aa80:c007:1736::]:443" -/* nickname=pushypebble */ +"45.84.107.200 orport=9100 id=9E2E162267A5F615AD8942EBAF90DC4297BC3D72" +" ipv6=[2a0d:bbc7::f816:3eff:feec:9f18]:9100" +/* nickname=prsv */ /* extrainfo=0 */ /* ===== */ , -"185.241.208.71 orport=143 id=AE8F944F2843C8072E491BA301B9F6EEFD6BDFDB" -" ipv6=[2a12:a800:2:1:185:241:208:71]:143" -/* nickname=Quetzalcoatl */ +"109.69.218.176 orport=443 id=FA7136FD4F8A727810A22ED2096AF60F872C2F41" +/* nickname=vandewoestijne */ /* extrainfo=0 */ /* ===== */ , -"51.15.232.19 orport=21 id=D49BB7514C78F68303D879AF7C3D5D67148F599B" -" ipv6=[2001:bc8:710:93a0:dc00:ff:fe7d:88a9]:21" -/* nickname=Layer13 */ +"64.65.1.142 orport=443 id=60EC7FF9D1922E8BE72878C15DD85932EE786ACA" +/* nickname=latto */ /* extrainfo=0 */ /* ===== */ , -"194.164.245.205 orport=443 id=E4C6E31D745BE31F9E150F3BEEE19235D9629FC9" -" ipv6=[2a13:d207:0:40e::1]:443" -/* nickname=tetris */ +"171.25.193.39 orport=81 id=9A561CA579F0918D4E0C7A8533801B91C56FD605" +" ipv6=[2001:67c:289c:2::40]:81" +/* nickname=DFRI79 */ /* extrainfo=0 */ /* ===== */ , -"94.23.45.103 orport=9001 id=EFA4C5E7E9215E8A3C7A8F3C74D3139667DA92A5" -" ipv6=[2001:41d0:2:2e67::1]:9001" -/* nickname=thicancyborg */ +"66.92.214.63 orport=9001 id=0E33CE0721903F24B5680E1105D19EC4D7D335EB" +/* nickname=forest07 */ /* extrainfo=0 */ /* ===== */ , -"107.189.6.124 orport=443 id=4746E2B86718D5391CCF18C258460C321945DBD8" -/* nickname=anarchy99 */ +"64.65.2.54 orport=443 id=8A5B9A2D0B37BE2F8ECFB14396EB4D432131D907" +/* nickname=bustarhymes */ /* extrainfo=0 */ /* ===== */ , -"185.129.61.10 orport=443 id=45D276D6A51DAE5C6F39A655ECE647DDEA9FAEF4" -" ipv6=[2001:67c:89c:702:1ce:1ce:babe:10]:443" -/* nickname=dotsrcExit10 */ +"78.47.189.21 orport=1984 id=B939F036D9BF7FEA590BE961BFAB4C2E0641AC36" +" ipv6=[2a01:4f8:c0c:358b::1]:1984" +/* nickname=ReDHumus */ /* extrainfo=0 */ /* ===== */ , -"23.105.163.117 orport=443 id=27132CE932038B4F34F3BB50299C8D8805735512" -/* nickname=catpain */ +"64.65.0.56 orport=443 id=FB6F6C38348F3879C568F7AD7282697E69274E77" +/* nickname=bishoplamont */ /* extrainfo=0 */ /* ===== */ , -"102.130.117.25 orport=443 id=9A0AAF2E43BE3744CD1D6CD532C861F5A568F7A9" -/* nickname=lnag */ +"140.78.100.26 orport=5443 id=70B2D83BFCA9502E37EAF49DC685166718EADEFE" +/* nickname=INSRelay26at5443 */ /* extrainfo=0 */ /* ===== */ , -"65.21.1.225 orport=9001 id=55C6187EB2BEBC968F4C89D25F4350889E6BC251" -" ipv6=[2a01:4f9:c011:8cca::1]:9001" -/* nickname=Freya */ +"92.27.11.80 orport=9001 id=C7865D58EEFE96B92333E3C8BE3C0AAAA0000EEF" +" ipv6=[2001:470:1f08:4c7::2]:9001" +/* nickname=RealityNews */ /* extrainfo=0 */ /* ===== */ , -"72.211.49.235 orport=443 id=66C7803C5F95CEC0D78004E15A0E4399CD0E4787" -/* nickname=nasrag01 */ +"96.9.98.140 orport=443 id=24167CC4D183585A6AA4192B770F611F9D69C043" +/* nickname=famousdex */ /* extrainfo=0 */ /* ===== */ , -"94.100.6.13 orport=9001 id=25F701E5ED2556CFEA55D81AF937EFBCDF9464FB" -/* nickname=cruffty9 */ +"50.103.128.207 orport=9006 id=D0B5734B42303C9FEDF5BDA1C2383C6195909A88" +/* nickname=raspberry */ /* extrainfo=0 */ /* ===== */ , -"171.25.193.20 orport=9050 id=FD1B84A26BC18B32D115B1B8A7048D6FC85248EE" -" ipv6=[2001:67c:289c::20]:9050" -/* nickname=DFRI35 */ +"81.16.33.42 orport=443 id=F21DFB7CCD5EEF3E021086EC96EF7CFCAA72F4F3" +/* nickname=pangea07 */ /* extrainfo=0 */ /* ===== */ , -"195.246.230.153 orport=9001 id=690137D4A1E3ACA5D35B09CD68DA8A3AE0291141" -/* nickname=Kheldell */ +"78.142.18.219 orport=8443 id=C05DCC87D7667D08EE4370D6CDB8CBEB6E0B4313" +/* nickname=bauruine */ /* extrainfo=0 */ /* ===== */ , -"68.8.241.30 orport=9001 id=581BB3AD0D242262B9168C2F17E2E909321BB0A0" -/* nickname=gothamKneadsMe */ +"171.25.193.36 orport=9001 id=F140945C1C795A367B0ACC5F67741857B73FA4B2" +" ipv6=[2001:67c:289c:2::35]:9001" +/* nickname=DFRI57 */ /* extrainfo=0 */ /* ===== */ , -"107.189.8.181 orport=443 id=DB451037C23AF3D028AE1B7E2F82BE5CA77B98A5" -" ipv6=[2605:6400:30:f49b:e2ee:34f8:c854:6f63]:443" -/* nickname=NgePTimE */ +"178.17.174.164 orport=443 id=9BAAA9CBA3109C2C807F2E84D5C9C0C8C147DCE6" +" ipv6=[2a00:1dc0:caff:73::a568]:443" +/* nickname=calator */ /* extrainfo=0 */ /* ===== */ , -"194.55.13.207 orport=443 id=B8F8E84576DE8CC6CDE136D2374F9385A2AFFAD0" -" ipv6=[2a03:4000:31:2f::2430]:9050" -/* nickname=cookieandtea */ +"64.65.62.115 orport=443 id=CE77E80343CCF0D68FAE60EC6637EF1829F64805" +/* nickname=jaykae */ /* extrainfo=0 */ /* ===== */ , -"165.73.242.163 orport=443 id=147321EDE839D266601E65A7FAAD306749B1EEC5" -/* nickname=AlexGraywood */ +"185.244.129.163 orport=9001 id=C171B79FF282D3394129D66D83AFEA85548138D1" +/* nickname=Sinker */ /* extrainfo=0 */ /* ===== */ , -"45.77.112.107 orport=443 id=3FBB6F16075E45BE8BC9BB7034D03A9B4EB6B6C7" -" ipv6=[2001:19f0:9003:9c8:ec4:7aff:fe8f:69aa]:443" -/* nickname=Aid6 */ +"82.67.111.215 orport=9001 id=E58D998896E2464A989D4107AB4403C8AD9F32AE" +/* nickname=GigaTorOfHell2 */ /* extrainfo=0 */ /* ===== */ , -"193.31.27.127 orport=9001 id=54476788A1AA7C348F20390DFC52ACA1352F4C57" -/* nickname=luna */ +"216.197.207.48 orport=9001 id=C366391E67A29CE959A15193D0CF2F9ED94F3578" +/* nickname=jorcanada */ /* extrainfo=0 */ /* ===== */ , -"86.60.148.189 orport=9001 id=16187AC3BDC2A0B030731AF5E27764022A7AFA51" -/* nickname=aurora */ +"140.238.97.211 orport=9001 id=0B53297F0BD687103A00A514E7D2AB83C70F3700" +/* nickname=ruffletor */ /* extrainfo=0 */ /* ===== */ , -"212.132.108.236 orport=443 id=66FB8688C203C247CEA828209FB4901D4BDCF4B9" -/* nickname=Vendetta7 */ +"124.198.131.121 orport=8430 id=8B70848F74BD5A90F6B9E0CB555E7D8C18FF325F" +" ipv6=[2a12:a800:11:1:124:198:131:121]:8430" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"217.79.179.177 orport=9001 id=3E53D3979DB07EFD736661C934A1DED14127B684" -" ipv6=[2001:4ba0:fff9:131:6c4f::90d3]:9001" -/* nickname=Unnamed */ +"50.65.178.92 orport=9001 id=E690103F3E388A3D9C125936F1AE5C64C1A26D51" +" ipv6=[2604:3d09:667c:9560::9]:9001" +/* nickname=affinezeussv */ /* extrainfo=0 */ /* ===== */ , -"45.138.16.76 orport=9000 id=90A83D3A6D53619211909E96EDC30C910676A32B" -" ipv6=[2a12:a800:2:1:45:138:16:76]:9000" -/* nickname=Quetzalcoatl */ +"73.68.62.87 orport=8443 id=CDB2605D2BD28DA31CC91956E8BAD147B7DF8AF9" +/* nickname=2mpdhack */ /* extrainfo=0 */ /* ===== */ , -"217.160.98.239 orport=9001 id=428CAF26607664A176DCD3549EC2BC40253F82D6" -/* nickname=RelayUli */ +"172.245.106.179 orport=9001 id=C300E4E60EB8A73ED017540B36A3C6CEEBBCD2A9" +" ipv6=[2001:470:1f07:8b9::f7ae]:9001" +/* nickname=breaker39 */ /* extrainfo=0 */ /* ===== */ , -"5.135.83.4 orport=9001 id=1172983321801BBFC519E081F967B77484CE71E8" -/* nickname=SparkLowway */ +"150.230.22.185 orport=9001 id=C42AB0BC0F7B4B7BB660F582B73C6A83AA89D245" +/* nickname=GEamsterdam */ /* extrainfo=0 */ /* ===== */ , -"199.247.31.1 orport=24752 id=D1B228DE5DEF2F8087AEBED4E2115EC5840ACC25" -/* nickname=Unnamed */ +"51.38.112.15 orport=9100 id=89F95502BDA81E44B67BADBFFF00DA80CDD4AFB5" +/* nickname=prsv */ /* extrainfo=0 */ /* ===== */ , -"185.112.146.168 orport=443 id=ED2F15C1B1BC20E3FA9618E949EB5872386F4AF4" -/* nickname=egdelord4life */ +"5.39.81.102 orport=9001 id=5500BAEEDC61A6685F687019196E1765171301D5" +" ipv6=[2001:41d0:8:9366::1]:9001" +/* nickname=p1onX01 */ /* extrainfo=0 */ /* ===== */ , -"79.137.198.213 orport=443 id=2AB6D4CE7A4D46ADA4F21C537A05A68DE088280B" -/* nickname=cozybeardev */ +"64.65.1.30 orport=443 id=6DE6F463227B87923C12C83157C21ECC8764E9B2" +/* nickname=joegifted */ /* extrainfo=0 */ /* ===== */ , -"51.81.93.108 orport=443 id=24523E7B004983EC4CA5033EBC9B7293F12F237C" -/* nickname=Luna */ +"64.65.2.43 orport=443 id=0842C38D6CDA0C9DA41032A43A4F30BF5264E13B" +/* nickname=pmddawn */ /* extrainfo=0 */ /* ===== */ , -"185.82.217.49 orport=9001 id=9665A1A6EB9B98C57E446A483E75E05F0539B41B" -" ipv6=[2a02:27aa::41]:9001" -/* nickname=Assange038bg */ +"45.138.16.240 orport=7430 id=B85E978AEE73A9604FD9B124E1D834080AFC3FA4" +" ipv6=[2a12:a800:2:1:45:138:16:240]:7430" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"64.31.10.6 orport=9000 id=BE9EECDBA47C16B8F687164D8F7E28620E0410D1" -/* nickname=sideshowbob */ +"195.218.16.136 orport=9001 id=2D8768E3EA8B974ADB69F7FA8140DBEAFC14C8F0" +/* nickname=NotMyMothersRelay */ /* extrainfo=0 */ /* ===== */ , -"84.149.73.149 orport=9005 id=CFB8CE28D1B12EEB8662511AFBC1D0C6F79065A8" -/* nickname=mytorrelay */ +"5.2.79.190 orport=9001 id=02A8CCB1FB70984226231283596DA734A80E3F6F" +/* nickname=onionDAOrel0aded1 */ /* extrainfo=0 */ /* ===== */ , -"111.69.37.214 orport=9001 id=9D70BB1EF20AD789574CD9D9BB2C1D2E9151B874" -/* nickname=Mak */ +"45.13.104.185 orport=9001 id=234D670EAA794F092F7BD758D5D2AA7F4E3FFBE3" +" ipv6=[2a0b:cbc0:1100:1a::1]:9001" +/* nickname=Ceres */ /* extrainfo=0 */ /* ===== */ , -"185.184.71.94 orport=9001 id=5AC2115B2C6E5A2382484EAEE5D9C7E9C229807A" -/* nickname=ididnteditheconfig */ +"124.198.131.62 orport=9000 id=49B422AB305669407516E4A0D4CE5BEACE3E2432" +" ipv6=[2a12:a800:11:1:124:198:131:62]:9000" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"195.90.215.218 orport=9997 id=C78689CFDC3EFB435FD62BE874639AEAAC9C353F" -/* nickname=TorTempel3 */ +"192.121.44.27 orport=9001 id=ABC5A7A6D5C609512F5D7CD2B490CE7366F00D60" +" ipv6=[2a09:be40:28ff:50:c4c9:3dff:fea3:f4fa]:9001" +/* nickname=Playstar02 */ /* extrainfo=0 */ /* ===== */ , -"116.255.1.163 orport=9001 id=6F42D6F51123C09886464A959F7F04D5AD494E96" -/* nickname=badc0ded */ +"64.65.1.144 orport=443 id=DEB01655570C9BCB968F6EEA95B2E4F85F6C99CF" +/* nickname=shine1k */ /* extrainfo=0 */ /* ===== */ , -"185.40.4.101 orport=12443 id=8CB12C1DDD2071C6F6CB09D73523689F1D351788" -" ipv6=[2a0e:4005:1002:ffff:185:40:4:101]:12443" -/* nickname=bauruine */ +"64.65.1.52 orport=443 id=137E23C6BA0863C229D68A64C0E0BD0F2D17D6D2" +/* nickname=greasymiami */ /* extrainfo=0 */ /* ===== */ , -"5.255.125.196 orport=443 id=CE9ED7FB244F80F6310A6DC399F904C202FD8068" -" ipv6=[2a04:52c0:130:896e::1]:443" -/* nickname=Truancy */ +"107.189.30.236 orport=9000 id=A4F42AE65F11634C42A3F3952E719F47091BD36F" +" ipv6=[2605:6400:30:f5a3:5bb1:af4e:c969:c73e]:9000" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"45.134.225.36 orport=10444 id=80A7B26CBDADE9CCEAEC648286CEA43C6AEA1903" -/* nickname=bauruine */ +"178.20.55.16 orport=19001 id=CFAB19E23290F5BA1F7FF24494D26FBD4E4DF6CE" +" ipv6=[2a00:1b88:4::2]:19001" +/* nickname=marcuse4 */ /* extrainfo=0 */ /* ===== */ , -"130.51.22.104 orport=6969 id=B5CDCE60218E99E5D1964B41D1BC307B54913C79" -/* nickname=halloworldtor */ +"82.223.103.104 orport=53421 id=5F6C321216267A086F6B3634BA4664297C504F5E" +" ipv6=[2001:ba0:214:a800::1]:53421" +/* nickname=TORkedOff */ /* extrainfo=0 */ /* ===== */ , -"172.233.187.241 orport=443 id=9B7A16AABCAFA62B6F10E7877B9F5728C838891B" -" ipv6=[2a01:7e04::f03c:95ff:fee8:7462]:443" -/* nickname=Unnamed */ +"108.181.57.251 orport=443 id=AFEAF3A9E0DB1D837BE8FF1983BA0C65A3E71D73" +/* nickname=osterreich */ /* extrainfo=0 */ /* ===== */ , -"185.101.139.172 orport=443 id=9CBD49371BDB88FB8FB278C25AE8A9F1DE1498EA" -/* nickname=NightRelay */ +"124.198.131.114 orport=8100 id=52F1B080FB427CEE1D3D190B97776B704879FA08" +" ipv6=[2a12:a800:11:1:124:198:131:114]:8100" +/* nickname=Quetzalcoatl */ /* extrainfo=0 */ /* ===== */ , -"94.16.31.131 orport=443 id=0B4190C676FAAD34EB2DCB9A288939476CEBCF32" -" ipv6=[2a00:11c0:60:2cf:d8b5:30ff:fe27:f208]:443" -/* nickname=FasterRelay */ +"135.125.183.193 orport=9300 id=949838C7EDCBC3AA0FF057935D2E7AD9184389BD" +" ipv6=[2001:41d0:701:1100::9e20]:9300" +/* nickname=prsv */ /* extrainfo=0 */ /* ===== */ , -"2.58.52.163 orport=9004 id=BBA4AC0A7CC698E97926AF69CE9A58AC26523CF9" -/* nickname=SomeTorinAS200462 */ +"37.221.195.103 orport=9001 id=C54AB7F3CCAB01BAF61A6F7337AE1F60D8BB940D" +" ipv6=[2a03:4000:8:61b:85e:b6ff:fefa:8752]:9001" +/* nickname=fedoriansRelayTor */ /* extrainfo=0 */ /* ===== */ , -"86.86.126.113 orport=443 id=FC83153EA2FF3807029506A4B30A27D953DD98D4" -" ipv6=[2a02:a452:9bf7:1:82ee:73ff:fe67:f076]:9001" -/* nickname=oneup */ +"45.89.127.221 orport=9001 id=9CCC3E2BC7FA56F602020AC9D77FE19A3727D0DD" +/* nickname=apalaris */ /* extrainfo=0 */ /* ===== */ , -"194.164.173.152 orport=21344 id=B4DBFFC07EB79EEC4F68F1EC657A9A6D3420F54B" -" ipv6=[2001:ba0:200:7a00:0:d26c:bdd4:6841]:21344" -/* nickname=gnampf4i33 */ +"23.129.64.202 orport=443 id=60904553C1C40F3C503F3F10E2F7F6DEBECD6CBF" +" ipv6=[2620:18c:0:192::e0:202]:443" +/* nickname=eo202 */ /* extrainfo=0 */ /* ===== */ , -"89.185.85.140 orport=443 id=F59D3D313A027703E51DC7DF793F2ED106C2E372" -" ipv6=[2a12:5940:9101::2]:443" -/* nickname=cozybeardev */ +"188.172.228.104 orport=443 id=83C8D4A066522D230D640FE3592A810C59669B25" +" ipv6=[2a0a:4cc0:3:10d::42]:443" +/* nickname=Totoro4220 */ /* extrainfo=0 */ /* ===== */ , -"194.26.192.77 orport=8100 id=7C6FDF1CEE7C924EE06C064708C9E1CC0BC8835C" -" ipv6=[2a12:a800:1:1:194:26:192:77]:8100" -/* nickname=Quetzalcoatl */ +"15.204.140.9 orport=8443 id=3FB88013FAC7AB8F479F33F5B484BE9F444330C3" +/* nickname=Parzival */ /* extrainfo=0 */ /* ===== */ , -"144.76.201.253 orport=4080 id=BA13324719485DC3B5FF258C21603287F1AFFD06" -" ipv6=[2a01:4f8:200:82ca::2]:4080" -/* nickname=freeassange */ +"95.216.145.1 orport=1066 id=B9C8AA1EA320CF1BD3E0D158C3E76705A2CB9D2C" +" ipv6=[2a01:4f9:c010:8fb::bee]:1066" +/* nickname=karnak */ /* extrainfo=0 */ /* ===== */ , -"185.220.101.142 orport=11142 id=B0543A3DF8D402F53998E03CFE1B35845DB27D9D" -" ipv6=[2a0b:f4c2:1::142]:11142" -/* nickname=relayon1142 */ +"144.217.90.187 orport=9001 id=7040C1F5728746C5FB5E12845101A26EE8636D7E" +" ipv6=[2607:5300:201:3100::5b0d]:9001" +/* nickname=SaruTorUmidanuki */ /* extrainfo=0 */ /* ===== */ , -"193.105.134.150 orport=9001 id=1808CDA40FDEFE9F1A117F89477BADC882C08A63" -/* nickname=ferrarizSchumacher */ +"51.81.222.62 orport=9001 id=7BC8F2680657BE6C51B51FF6EE113E739D85EDDE" +" ipv6=[2604:2dc0:202:300::ed3]:9001" +/* nickname=Tor2DotTeitelNet */ /* extrainfo=0 */ /* ===== */ , -"167.114.103.133 orport=443 id=D5E9356A5958E4891A124FB749829B30EB7F8D29" -/* nickname=Osiris */ +"82.153.138.57 orport=9003 id=6C5496CC85F96FF6B4BE0B2952A523BEB84184E6" +/* nickname=obzgs5tbmn4q */ /* extrainfo=0 */ /* ===== */ , -"65.49.20.10 orport=9001 id=D35682AB6E29D91AA030E03A9BEB42700D96A1EF" -/* nickname=BraveKhafre */ +"107.189.7.144 orport=9100 id=4EFF3D0C9DE539CF1E27BFC5B3E23BC7CB2D41A9" +" ipv6=[2605:6400:30:f1fa:f57f:d285:3ed9:ee27]:9100" +/* nickname=Quetzalcoatl */ +/* extrainfo=0 */ +/* ===== */ +, +"78.142.18.219 orport=12444 id=92F187D29A0F0DAEB929511D8870F3E9F0F46D46" +/* nickname=bauruine */ /* extrainfo=0 */ /* ===== */ , diff -Nru tor-0.4.8.16/src/app/config/include.am tor-0.4.9.6/src/app/config/include.am --- tor-0.4.8.16/src/app/config/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/app/config/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -16,7 +16,6 @@ src/app/config/statefile.h \ src/app/config/tor_cmdline_mode.h - noinst_HEADERS += \ src/app/config/auth_dirs.inc \ src/app/config/fallback_dirs.inc \ diff -Nru tor-0.4.8.16/src/app/config/or_options_st.h tor-0.4.9.6/src/app/config/or_options_st.h --- tor-0.4.8.16/src/app/config/or_options_st.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/app/config/or_options_st.h 2026-03-25 14:30:34.000000000 +0000 @@ -89,6 +89,10 @@ char *KeyDirectory; /**< Where to store keys data, as modified. */ int KeyDirectoryGroupReadable; /**< Boolean: Is the KeyDirectory g+r? */ + char *FamilyKeyDirectory_option; /**< Where to look for family ID keys, + * as configured by the user. */ + char *FamilyKeyDirectory; /**< Where to look for family ID keys. */ + char *CacheDirectory_option; /**< Where to store cached data, as * configured by the user. */ char *CacheDirectory; /**< Where to store cached data, as modified. */ @@ -141,6 +145,8 @@ * Includes OutboundBindAddresses and * configured ports. */ int ReducedExitPolicy; /**

This is a SOCKs proxy, not an HTTP proxy.

\n" + "

This is a SOCKS proxy, not an HTTP proxy.

\n" "

\n" "It appears you have configured your web browser to use this Tor port as\n" "an HTTP proxy.\n" - "

\n" + "

\n" + "

\n" "This is not correct: This port is configured as a SOCKS proxy, not\n" "an HTTP proxy. If you need an HTTP proxy tunnel, use the HTTPTunnelPort\n" "configuration option in place of, or in addition to, SOCKSPort.\n" diff -Nru tor-0.4.8.16/src/ext/include.am tor-0.4.9.6/src/ext/include.am --- tor-0.4.8.16/src/ext/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/ext/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -6,15 +6,15 @@ EXTRA_DIST += src/ext/ext.md EXTHEADERS = \ - src/ext/ht.h \ - src/ext/byteorder.h \ - src/ext/tinytest.h \ + src/ext/ht.h \ + src/ext/byteorder.h \ + src/ext/tinytest.h \ src/ext/tor_readpassphrase.h \ - src/ext/strlcat.c \ - src/ext/strlcpy.c \ - src/ext/getdelim.c \ + src/ext/strlcat.c \ + src/ext/strlcpy.c \ + src/ext/getdelim.c \ src/ext/tinytest_macros.h \ - src/ext/tor_queue.h \ + src/ext/tor_queue.h \ src/ext/siphash.h \ src/ext/compat_blake2.h \ src/ext/timeouts/timeout.h \ @@ -216,6 +216,21 @@ noinst_LIBRARIES += $(LIBKECCAK_TINY) endif +src_ext_polyval_libpolyval_a_CFLAGS=\ + @CFLAGS_CONSTTIME@ +src_ext_polyval_libpolyval_a_SOURCES= \ + src/ext/polyval/polyval.c + +POLYVAL_HDRS = \ + src/ext/polyval/polyval.h \ + src/ext/polyval/pclmul.c \ + src/ext/polyval/ctmul64.c \ + src/ext/polyval/ctmul.c + +noinst_HEADERS += $(POLYVAL_HDRS) +LIBPOLYVAL=src/ext/polyval/libpolyval.a +noinst_LIBRARIES += $(LIBPOLYVAL) + EXTRA_DIST += \ src/ext/timeouts/bench/bench-add.lua \ src/ext/timeouts/bench/bench-aux.lua \ diff -Nru tor-0.4.8.16/src/ext/polyval/ctmul.c tor-0.4.9.6/src/ext/polyval/ctmul.c --- tor-0.4.8.16/src/ext/polyval/ctmul.c 1970-01-01 00:00:00.000000000 +0000 +++ tor-0.4.9.6/src/ext/polyval/ctmul.c 2026-03-25 14:30:34.000000000 +0000 @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * We compute "carryless multiplications" through normal integer + * multiplications, masking out enough bits to create "holes" in which + * carries may expand without altering our bits; we really use 8 data + * bits per 32-bit word, spaced every fourth bit. Accumulated carries + * may not exceed 8 in total, which fits in 4 bits. + * + * It would be possible to use a 3-bit spacing, allowing two operands, + * one with 7 non-zero data bits, the other one with 10 or 11 non-zero + * data bits; this asymmetric splitting makes the overall code more + * complex with thresholds and exceptions, and does not appear to be + * worth the effort. + */ + +/* + * We cannot really autodetect whether multiplications are "slow" or + * not. A typical example is the ARM Cortex M0+, which exists in two + * versions: one with a 1-cycle multiplication opcode, the other with + * a 32-cycle multiplication opcode. They both use exactly the same + * architecture and ABI, and cannot be distinguished from each other + * at compile-time. + * + * Since most modern CPU (even embedded CPU) still have fast + * multiplications, we use the "fast mul" code by default. + */ + +// A 32x32 -> 64 multiply. +#define MUL(x, y) (((uint64_t)(x)) * ((uint64_t)(y))) + +#ifdef BR_SLOW_MUL + +/* + * This implementation uses Karatsuba-like reduction to make fewer + * integer multiplications (9 instead of 16), at the expense of extra + * logical operations (XOR, shifts...). On modern x86 CPU that offer + * fast, pipelined multiplications, this code is about twice slower than + * the simpler code with 16 multiplications. This tendency may be + * reversed on low-end platforms with expensive multiplications. + */ + +#define MUL32(h, l, x, y) do { \ + uint64_t mul32tmp = MUL(x, y); \ + (h) = (uint32_t)(mul32tmp >> 32); \ + (l) = (uint32_t)mul32tmp; \ + } while (0) + +static inline void +bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y) +{ + uint32_t x0, x1, x2, x3; + uint32_t y0, y1, y2, y3; + uint32_t a0, a1, a2, a3, a4, a5, a6, a7, a8; + uint32_t b0, b1, b2, b3, b4, b5, b6, b7, b8; + + x0 = x & (uint32_t)0x11111111; + x1 = x & (uint32_t)0x22222222; + x2 = x & (uint32_t)0x44444444; + x3 = x & (uint32_t)0x88888888; + y0 = y & (uint32_t)0x11111111; + y1 = y & (uint32_t)0x22222222; + y2 = y & (uint32_t)0x44444444; + y3 = y & (uint32_t)0x88888888; + + /* + * (x0+W*x1)*(y0+W*y1) -> a0:b0 + * (x2+W*x3)*(y2+W*y3) -> a3:b3 + * ((x0+x2)+W*(x1+x3))*((y0+y2)+W*(y1+y3)) -> a6:b6 + */ + a0 = x0; + b0 = y0; + a1 = x1 >> 1; + b1 = y1 >> 1; + a2 = a0 ^ a1; + b2 = b0 ^ b1; + a3 = x2 >> 2; + b3 = y2 >> 2; + a4 = x3 >> 3; + b4 = y3 >> 3; + a5 = a3 ^ a4; + b5 = b3 ^ b4; + a6 = a0 ^ a3; + b6 = b0 ^ b3; + a7 = a1 ^ a4; + b7 = b1 ^ b4; + a8 = a6 ^ a7; + b8 = b6 ^ b7; + + MUL32(b0, a0, b0, a0); + MUL32(b1, a1, b1, a1); + MUL32(b2, a2, b2, a2); + MUL32(b3, a3, b3, a3); + MUL32(b4, a4, b4, a4); + MUL32(b5, a5, b5, a5); + MUL32(b6, a6, b6, a6); + MUL32(b7, a7, b7, a7); + MUL32(b8, a8, b8, a8); + + a0 &= (uint32_t)0x11111111; + a1 &= (uint32_t)0x11111111; + a2 &= (uint32_t)0x11111111; + a3 &= (uint32_t)0x11111111; + a4 &= (uint32_t)0x11111111; + a5 &= (uint32_t)0x11111111; + a6 &= (uint32_t)0x11111111; + a7 &= (uint32_t)0x11111111; + a8 &= (uint32_t)0x11111111; + b0 &= (uint32_t)0x11111111; + b1 &= (uint32_t)0x11111111; + b2 &= (uint32_t)0x11111111; + b3 &= (uint32_t)0x11111111; + b4 &= (uint32_t)0x11111111; + b5 &= (uint32_t)0x11111111; + b6 &= (uint32_t)0x11111111; + b7 &= (uint32_t)0x11111111; + b8 &= (uint32_t)0x11111111; + + a2 ^= a0 ^ a1; + b2 ^= b0 ^ b1; + a0 ^= (a2 << 1) ^ (a1 << 2); + b0 ^= (b2 << 1) ^ (b1 << 2); + a5 ^= a3 ^ a4; + b5 ^= b3 ^ b4; + a3 ^= (a5 << 1) ^ (a4 << 2); + b3 ^= (b5 << 1) ^ (b4 << 2); + a8 ^= a6 ^ a7; + b8 ^= b6 ^ b7; + a6 ^= (a8 << 1) ^ (a7 << 2); + b6 ^= (b8 << 1) ^ (b7 << 2); + a6 ^= a0 ^ a3; + b6 ^= b0 ^ b3; + *lo = a0 ^ (a6 << 2) ^ (a3 << 4); + *hi = b0 ^ (b6 << 2) ^ (b3 << 4) ^ (a6 >> 30) ^ (a3 >> 28); +} + +#else + +/* + * Simple multiplication in GF(2)[X], using 16 integer multiplications. + */ + +static inline void +bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y) +{ + uint32_t x0, x1, x2, x3; + uint32_t y0, y1, y2, y3; + uint64_t z0, z1, z2, z3; + uint64_t z; + + x0 = x & (uint32_t)0x11111111; + x1 = x & (uint32_t)0x22222222; + x2 = x & (uint32_t)0x44444444; + x3 = x & (uint32_t)0x88888888; + y0 = y & (uint32_t)0x11111111; + y1 = y & (uint32_t)0x22222222; + y2 = y & (uint32_t)0x44444444; + y3 = y & (uint32_t)0x88888888; + z0 = MUL(x0, y0) ^ MUL(x1, y3) ^ MUL(x2, y2) ^ MUL(x3, y1); + z1 = MUL(x0, y1) ^ MUL(x1, y0) ^ MUL(x2, y3) ^ MUL(x3, y2); + z2 = MUL(x0, y2) ^ MUL(x1, y1) ^ MUL(x2, y0) ^ MUL(x3, y3); + z3 = MUL(x0, y3) ^ MUL(x1, y2) ^ MUL(x2, y1) ^ MUL(x3, y0); + z0 &= (uint64_t)0x1111111111111111; + z1 &= (uint64_t)0x2222222222222222; + z2 &= (uint64_t)0x4444444444444444; + z3 &= (uint64_t)0x8888888888888888; + z = z0 | z1 | z2 | z3; + *lo = (uint32_t)z; + *hi = (uint32_t)(z >> 32); +} + +#endif + +static void +pv_mul_y_h_ctmul(polyval_t *pv) +{ + uint32_t *yw = pv->y.v; + const uint32_t *hw = pv->key.h.v; + + /* + * Throughout the loop we handle the y and h values as arrays + * of 32-bit words. + */ + { + int i; + uint32_t a[9], b[9], zw[8]; + uint32_t c0, c1, c2, c3, d0, d1, d2, d3, e0, e1, e2, e3; + + /* + * We multiply two 128-bit field elements. We use + * Karatsuba to turn that into three 64-bit + * multiplications, which are themselves done with a + * total of nine 32-bit multiplications. + */ + + /* + * y[0,1]*h[0,1] -> 0..2 + * y[2,3]*h[2,3] -> 3..5 + * (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6..8 + */ + a[0] = yw[0]; + b[0] = hw[0]; + a[1] = yw[1]; + b[1] = hw[1]; + a[2] = a[0] ^ a[1]; + b[2] = b[0] ^ b[1]; + + a[3] = yw[2]; + b[3] = hw[2]; + a[4] = yw[3]; + b[4] = hw[3]; + a[5] = a[3] ^ a[4]; + b[5] = b[3] ^ b[4]; + + a[6] = a[0] ^ a[3]; + b[6] = b[0] ^ b[3]; + a[7] = a[1] ^ a[4]; + b[7] = b[1] ^ b[4]; + a[8] = a[6] ^ a[7]; + b[8] = b[6] ^ b[7]; + + for (i = 0; i < 9; i ++) { + bmul(&b[i], &a[i], b[i], a[i]); + } + + c0 = a[0]; + c1 = b[0] ^ a[2] ^ a[0] ^ a[1]; + c2 = a[1] ^ b[2] ^ b[0] ^ b[1]; + c3 = b[1]; + d0 = a[3]; + d1 = b[3] ^ a[5] ^ a[3] ^ a[4]; + d2 = a[4] ^ b[5] ^ b[3] ^ b[4]; + d3 = b[4]; + e0 = a[6]; + e1 = b[6] ^ a[8] ^ a[6] ^ a[7]; + e2 = a[7] ^ b[8] ^ b[6] ^ b[7]; + e3 = b[7]; + + e0 ^= c0 ^ d0; + e1 ^= c1 ^ d1; + e2 ^= c2 ^ d2; + e3 ^= c3 ^ d3; + c2 ^= e0; + c3 ^= e1; + d0 ^= e2; + d1 ^= e3; + +#if 0 + // This rotation is GHASH-only. + /* + * GHASH specification has the bits "reversed" (most + * significant is in fact least significant), which does + * not matter for a carryless multiplication, except that + * the 255-bit result must be shifted by 1 bit. + */ + zw[0] = c0 << 1; + zw[1] = (c1 << 1) | (c0 >> 31); + zw[2] = (c2 << 1) | (c1 >> 31); + zw[3] = (c3 << 1) | (c2 >> 31); + zw[4] = (d0 << 1) | (c3 >> 31); + zw[5] = (d1 << 1) | (d0 >> 31); + zw[6] = (d2 << 1) | (d1 >> 31); + zw[7] = (d3 << 1) | (d2 >> 31); +#else + zw[0] = c0; + zw[1] = c1; + zw[2] = c2; + zw[3] = c3; + zw[4] = d0; + zw[5] = d1; + zw[6] = d2; + zw[7] = d3; +#endif + + /* + * We now do the reduction modulo the field polynomial + * to get back to 128 bits. + */ + for (i = 0; i < 4; i ++) { + uint32_t lw; + + lw = zw[i]; + zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7); + zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25); + } + memcpy(yw, zw + 4, 16); + } +} +#undef MUL diff -Nru tor-0.4.8.16/src/ext/polyval/ctmul64.c tor-0.4.9.6/src/ext/polyval/ctmul64.c --- tor-0.4.8.16/src/ext/polyval/ctmul64.c 1970-01-01 00:00:00.000000000 +0000 +++ tor-0.4.9.6/src/ext/polyval/ctmul64.c 2026-03-25 14:30:34.000000000 +0000 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2016 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * This is the 64-bit variant of br_ghash_ctmul32(), with 64-bit operands + * and bit reversal of 64-bit words. + */ + +static inline uint64_t +bmul64(uint64_t x, uint64_t y) +{ + uint64_t x0, x1, x2, x3; + uint64_t y0, y1, y2, y3; + uint64_t z0, z1, z2, z3; + + x0 = x & (uint64_t)0x1111111111111111; + x1 = x & (uint64_t)0x2222222222222222; + x2 = x & (uint64_t)0x4444444444444444; + x3 = x & (uint64_t)0x8888888888888888; + y0 = y & (uint64_t)0x1111111111111111; + y1 = y & (uint64_t)0x2222222222222222; + y2 = y & (uint64_t)0x4444444444444444; + y3 = y & (uint64_t)0x8888888888888888; + z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1); + z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2); + z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3); + z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0); + z0 &= (uint64_t)0x1111111111111111; + z1 &= (uint64_t)0x2222222222222222; + z2 &= (uint64_t)0x4444444444444444; + z3 &= (uint64_t)0x8888888888888888; + return z0 | z1 | z2 | z3; +} + +static uint64_t +rev64(uint64_t x) +{ +#define RMS(m, s) do { \ + x = ((x & (uint64_t)(m)) << (s)) \ + | ((x >> (s)) & (uint64_t)(m)); \ + } while (0) + + RMS(0x5555555555555555, 1); + RMS(0x3333333333333333, 2); + RMS(0x0F0F0F0F0F0F0F0F, 4); + RMS(0x00FF00FF00FF00FF, 8); + RMS(0x0000FFFF0000FFFF, 16); + return (x << 32) | (x >> 32); + +#undef RMS +} + + +static void +pv_mul_y_h_ctmul64(polyval_t *pv) +{ + uint64_t y0, y1; + uint64_t h0, h1, h2, h0r, h1r, h2r; + + y0 = CTMUL64_MEMBER(pv->y).lo; + y1 = CTMUL64_MEMBER(pv->y).hi; + h0 = CTMUL64_MEMBER(pv->key.h).lo; + h1 = CTMUL64_MEMBER(pv->key.h).hi; + h0r = rev64(h0); + h1r = rev64(h1); + + h2 = h0 ^ h1; + h2r = h0r ^ h1r; + { + uint64_t y0r, y1r, y2, y2r; + uint64_t z0, z1, z2, z0h, z1h, z2h; + uint64_t v0, v1, v2, v3; + + y0r = rev64(y0); + y1r = rev64(y1); + y2 = y0 ^ y1; + y2r = y0r ^ y1r; + + z0 = bmul64(y0, h0); + z1 = bmul64(y1, h1); + z2 = bmul64(y2, h2); + z0h = bmul64(y0r, h0r); + z1h = bmul64(y1r, h1r); + z2h = bmul64(y2r, h2r); + z2 ^= z0 ^ z1; + z2h ^= z0h ^ z1h; + z0h = rev64(z0h) >> 1; + z1h = rev64(z1h) >> 1; + z2h = rev64(z2h) >> 1; + + v0 = z0; + v1 = z0h ^ z2; + v2 = z1 ^ z2h; + v3 = z1h; + +#if 0 + // This step is GHASH only. + v3 = (v3 << 1) | (v2 >> 63); + v2 = (v2 << 1) | (v1 >> 63); + v1 = (v1 << 1) | (v0 >> 63); + v0 = (v0 << 1); +#endif + + v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7); + v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57); + v3 ^= v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7); + v2 ^= (v1 << 63) ^ (v1 << 62) ^ (v1 << 57); + + CTMUL64_MEMBER(pv->y).lo = v2; + CTMUL64_MEMBER(pv->y).hi = v3; + } +} diff -Nru tor-0.4.8.16/src/ext/polyval/pclmul.c tor-0.4.9.6/src/ext/polyval/pclmul.c --- tor-0.4.8.16/src/ext/polyval/pclmul.c 1970-01-01 00:00:00.000000000 +0000 +++ tor-0.4.9.6/src/ext/polyval/pclmul.c 2026-03-25 14:30:34.000000000 +0000 @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2017 Thomas Pornin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * This is the GHASH implementation that leverages the pclmulqdq opcode + * (from the AES-NI instructions). + */ + +#include + +#ifndef __GNUC__ +#define __attribute__(x) +#endif + +#define BR_TARGET(x) __attribute__((target(x))) + +#if defined(__GNUC__) && !defined(__clang__) + _Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul\")") +#endif + +#if 0 +/* + * Test CPU support for PCLMULQDQ. + */ +static inline int +pclmul_supported(void) +{ + /* + * Bit mask for features in ECX: + * 1 PCLMULQDQ support + */ + return br_cpuid(0, 0, 0x00000002, 0); +} + +/* see bearssl_hash.h */ +br_ghash +br_ghash_pclmul_get(void) +{ + return pclmul_supported() ? &br_ghash_pclmul : 0; +} + +BR_TARGETS_X86_UP +#endif +/* + * Call pclmulqdq. Clang appears to have trouble with the intrinsic, so, + * for that compiler, we use inline assembly. Inline assembly is + * potentially a bit slower because the compiler does not understand + * what the opcode does, and thus cannot optimize instruction + * scheduling. + * + * We use a target of "sse2" only, so that Clang may still handle the + * '__m128i' type and allocate SSE2 registers. + */ +#ifdef __clang__AND_NOT_WORKING + BR_TARGET("sse2") +static inline __m128i +pclmulqdq00(__m128i x, __m128i y) +{ + __asm__ ("pclmulqdq $0x00, %1, %0" : "+x" (x) : "x" (y)); + return x; +} +BR_TARGET("sse2") +static inline __m128i +pclmulqdq11(__m128i x, __m128i y) +{ + __asm__ ("pclmulqdq $0x11, %1, %0" : "+x" (x) : "x" (y)); + return x; +} +#else +#define pclmulqdq00(x, y) _mm_clmulepi64_si128(x, y, 0x00) +#define pclmulqdq11(x, y) _mm_clmulepi64_si128(x, y, 0x11) +#endif + +/* + * From a 128-bit value kw, compute kx as the XOR of the two 64-bit + * halves of kw (into the right half of kx; left half is unspecified). + */ +#define BK(kw, kx) do { \ + kx = _mm_xor_si128(kw, _mm_shuffle_epi32(kw, 0x0E)); \ + } while (0) + +/* + * Combine two 64-bit values (k0:k1) into a 128-bit (kw) value and + * the XOR of the two values (kx). + */ +#define PBK(k0, k1, kw, kx) do { \ + kw = _mm_unpacklo_epi64(k1, k0); \ + kx = _mm_xor_si128(k0, k1); \ + } while (0) + +/* + * Perform reduction in GF(2^128). The 256-bit value is in x0..x3; + * result is written in x0..x1. + */ +#define REDUCE_F128(x0, x1, x2, x3) do { \ + x1 = _mm_xor_si128( \ + x1, \ + _mm_xor_si128( \ + _mm_xor_si128( \ + x3, \ + _mm_srli_epi64(x3, 1)), \ + _mm_xor_si128( \ + _mm_srli_epi64(x3, 2), \ + _mm_srli_epi64(x3, 7)))); \ + x2 = _mm_xor_si128( \ + _mm_xor_si128( \ + x2, \ + _mm_slli_epi64(x3, 63)), \ + _mm_xor_si128( \ + _mm_slli_epi64(x3, 62), \ + _mm_slli_epi64(x3, 57))); \ + x0 = _mm_xor_si128( \ + x0, \ + _mm_xor_si128( \ + _mm_xor_si128( \ + x2, \ + _mm_srli_epi64(x2, 1)), \ + _mm_xor_si128( \ + _mm_srli_epi64(x2, 2), \ + _mm_srli_epi64(x2, 7)))); \ + x1 = _mm_xor_si128( \ + _mm_xor_si128( \ + x1, \ + _mm_slli_epi64(x2, 63)), \ + _mm_xor_si128( \ + _mm_slli_epi64(x2, 62), \ + _mm_slli_epi64(x2, 57))); \ + } while (0) + + +BR_TARGET("ssse3,pclmul") +static inline void +expand_key_pclmul(const polyval_t *pv, pv_expanded_key_t *out) +{ + __m128i h1w, h1x; + __m128i lastw, lastx; + __m128i t0, t1, t2, t3; + + h1w = PCLMUL_MEMBER(pv->key.h); + BK(h1w, h1x); + lastw = h1w; + + for (int i = PV_BLOCK_STRIDE - 2; i >= 0; --i) { + BK(lastw, lastx); + + t1 = pclmulqdq11(lastw, h1w); + t3 = pclmulqdq00(lastw, h1w); + t2 = pclmulqdq00(lastx, h1x); + t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3)); + t0 = _mm_shuffle_epi32(t1, 0x0E); + t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E)); + t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E)); + REDUCE_F128(t0, t1, t2, t3); + out->k[i] = lastw = _mm_unpacklo_epi64(t1, t0); + } +} + +// Add PCLMUL_BLOCK_STRIDE * 16 bytes from input. +BR_TARGET("ssse3,pclmul") +static inline void +pv_add_multiple_pclmul(polyval_t *pv, + const uint8_t *input, + const pv_expanded_key_t *expanded) +{ + __m128i t0, t1, t2, t3; + + t1 = _mm_setzero_si128(); + t2 = _mm_setzero_si128(); + t3 = _mm_setzero_si128(); + + for (int i = 0; i < PV_BLOCK_STRIDE; ++i, input += 16) { + __m128i aw = _mm_loadu_si128((void *)(input)); + __m128i ax; + __m128i hx, hw; + if (i == 0) { + aw = _mm_xor_si128(aw, PCLMUL_MEMBER(pv->y)); + } + if (i == PV_BLOCK_STRIDE - 1) { + hw = PCLMUL_MEMBER(pv->key.h); + } else { + hw = expanded->k[i]; + } + BK(aw, ax); + BK(hw, hx); + t1 = _mm_xor_si128(t1, pclmulqdq11(aw, hw)); + t3 = _mm_xor_si128(t3, pclmulqdq00(aw, hw)); + t2 = _mm_xor_si128(t2, pclmulqdq00(ax, hx)); + } + + t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3)); + t0 = _mm_shuffle_epi32(t1, 0x0E); + t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E)); + t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E)); + + REDUCE_F128(t0, t1, t2, t3); + PCLMUL_MEMBER(pv->y) = _mm_unpacklo_epi64(t1, t0); +} + + +/* see bearssl_hash.h */ +BR_TARGET("ssse3,pclmul") +static inline void +pv_mul_y_h_pclmul(polyval_t *pv) +{ + __m128i yw, h1w, h1x; + + h1w = PCLMUL_MEMBER(pv->key.h); + BK(h1w, h1x); + + { + __m128i aw, ax; + __m128i t0, t1, t2, t3; + + aw = PCLMUL_MEMBER(pv->y); + BK(aw, ax); + + t1 = pclmulqdq11(aw, h1w); + t3 = pclmulqdq00(aw, h1w); + t2 = pclmulqdq00(ax, h1x); + t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3)); + t0 = _mm_shuffle_epi32(t1, 0x0E); + t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E)); + t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E)); +#if 0 // This step is GHASH-only. + SL_256(t0, t1, t2, t3); +#endif + REDUCE_F128(t0, t1, t2, t3); + yw = _mm_unpacklo_epi64(t1, t0); + } + + PCLMUL_MEMBER(pv->y) = yw; +} diff -Nru tor-0.4.8.16/src/ext/polyval/polyval.c tor-0.4.9.6/src/ext/polyval/polyval.c --- tor-0.4.8.16/src/ext/polyval/polyval.c 1970-01-01 00:00:00.000000000 +0000 +++ tor-0.4.9.6/src/ext/polyval/polyval.c 2026-03-25 14:30:34.000000000 +0000 @@ -0,0 +1,561 @@ +/* Copyright (c) 2025, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file polyval.h + * \brief Implementation for polyval universal hash function. + * + * Polyval, which was first defined for AES-GCM-SIV, is a + * universal hash based on multiplication in GF(2^128). + * Unlike the more familiar GHASH, it is defined to work on + * little-endian inputs, and so is more straightforward and efficient + * on little-endian architectures. + * + * In Tor we use it as part of the Counter Galois Onion relay + * encryption format. + **/ + +/* Implementation notes: + * + * Our implementation is based on the GHASH code from BearSSL + * by Thomas Pornin. There are three implementations: + * + * pclmul.c -- An x86-only version, based on the CLMUL instructions + * introduced for westlake processors in 2010. + * + * ctmul64.c -- A portable contant-time implementation for 64-bit + * processors. + * + * ctmul.c -- A portable constant-time implementation for 32-bit + * processors with an efficient 32x32->64 multiply instruction. + * + * Note that the "ctmul" implementations are only constant-time + * if the corresponding CPU multiply and rotate instructions are + * also constant-time. But that's an architectural assumption we + * make in Tor. + */ + +#include "ext/polyval/polyval.h" +#include "lib/cc/compat_compiler.h" + +#include + +#ifdef PV_USE_PCLMUL_DETECT +#include +#endif + +typedef pv_u128_ u128; + +/* ======== + * We declare these functions, to help implement polyval. + * + * They have different definitions depending on our representation + * of 128-bit integers. + */ +#if 0 +/** + * Read a u128-bit little-endian integer from 'bytes', + * which may not be aligned. + */ +static inline u128 u128_from_bytes(const uint8_t *bytes); +/** + * Store a u128-bit little-endian integer to 'bytes_out', + * which may not be aligned. + */ +static inline void u128_to_bytes(u128, uint8_t *bytes_out); +/** + * XOR a u128 into the y field of a polyval_t struct. + * + * (Within the polyval struct, perform "y ^= v"). + */ +static inline void pv_xor_y(polyval_t *, u128 v); + +/* ======== + * The function which we expect our backend to implement. + */ +/** + * Within the polyval struct, perform "y *= h". + * + * (This is a carryless multiply in the Polyval galois field) + */ +static void pv_mul_y_h(polyval_t *);h +#endif + +/* ===== + * Endianness conversion for big-endian platforms + */ +#ifdef WORDS_BIGENDIAN +#ifdef __GNUC__ +#define bswap64(x) __builtin_bswap64(x) +#define bswap32(x) __builtin_bswap32(x) +#else +/* The (compiler should optimize these into a decent bswap instruction) */ +static inline uint64_t +bswap64(uint64_t value) +{ + return + ((value & 0xFF00000000000000) >> 56) | + ((value & 0x00FF000000000000) >> 40) | + ((value & 0x0000FF0000000000) >> 24) | + ((value & 0x000000FF00000000) >> 8) | + ((value & 0x00000000FF000000) << 8) | + ((value & 0x0000000000FF0000) << 24) | + ((value & 0x000000000000FF00) << 40) | + ((value & 0x00000000000000FF) << 56); +} + +static inline uint32_t +bswap32(uint32_t value) +{ + return + ((value & 0xFF000000) >> 24) | + ((value & 0x00FF0000) >> 8) | + ((value & 0x0000FF00) << 8) | + ((value & 0x000000FF) << 24); +} +#endif +#endif + +#ifdef WORDS_BIGENDIAN +#define convert_byte_order64(x) bswap64(x) +#define convert_byte_order32(x) bswap32(x) +#else +#define convert_byte_order64(x) (x) +#define convert_byte_order32(x) (x) +#endif + +#if defined PV_USE_PCLMUL_UNCONDITIONAL +#define PCLMUL_MEMBER(v) (v) +#define PV_USE_PCLMUL + +#elif defined PV_USE_PCLMUL_DETECT +#define PCLMUL_MEMBER(v) (v).u128x1 +#define CTMUL64_MEMBER(v) (v).u64x2 +#define PV_USE_PCLMUL +#define PV_USE_CTMUL64 + +#elif defined PV_USE_CTMUL64 +#define CTMUL64_MEMBER(v) (v) +#endif + +#ifdef PV_USE_PCLMUL +#include "ext/polyval/pclmul.c" + +DISABLE_GCC_WARNING("-Waggregate-return") +static inline u128 +u128_from_bytes_pclmul(const uint8_t *bytes) +{ + u128 r; + PCLMUL_MEMBER(r) = _mm_loadu_si128((const __m128i*)bytes); + return r; +} +ENABLE_GCC_WARNING("-Waggregate-return") + +static inline void +u128_to_bytes_pclmul(u128 val, uint8_t *bytes_out) +{ + _mm_storeu_si128((__m128i*)bytes_out, PCLMUL_MEMBER(val)); +} +static inline void +pv_xor_y_pclmul(polyval_t *pv, u128 v) +{ + PCLMUL_MEMBER(pv->y) = _mm_xor_si128(PCLMUL_MEMBER(pv->y), + PCLMUL_MEMBER(v)); +} +#endif + +#if defined(PV_USE_CTMUL64) +#include "ext/polyval/ctmul64.c" + +DISABLE_GCC_WARNING("-Waggregate-return") +static inline u128 +u128_from_bytes_ctmul64(const uint8_t *bytes) +{ + u128 r; + memcpy(&CTMUL64_MEMBER(r).lo, bytes, 8); + memcpy(&CTMUL64_MEMBER(r).hi, bytes + 8, 8); + CTMUL64_MEMBER(r).lo = convert_byte_order64(CTMUL64_MEMBER(r).lo); + CTMUL64_MEMBER(r).hi = convert_byte_order64(CTMUL64_MEMBER(r).hi); + return r; +} +ENABLE_GCC_WARNING("-Waggregate-return") + +static inline void +u128_to_bytes_ctmul64(u128 val, uint8_t *bytes_out) +{ + uint64_t lo = convert_byte_order64(CTMUL64_MEMBER(val).lo); + uint64_t hi = convert_byte_order64(CTMUL64_MEMBER(val).hi); + memcpy(bytes_out, &lo, 8); + memcpy(bytes_out + 8, &hi, 8); +} +static inline void +pv_xor_y_ctmul64(polyval_t *pv, u128 val) +{ + CTMUL64_MEMBER(pv->y).lo ^= CTMUL64_MEMBER(val).lo; + CTMUL64_MEMBER(pv->y).hi ^= CTMUL64_MEMBER(val).hi; +} +#endif + +#if defined(PV_USE_CTMUL) +#include "ext/polyval/ctmul.c" + +DISABLE_GCC_WARNING("-Waggregate-return") +static inline u128 +u128_from_bytes_ctmul(const uint8_t *bytes) +{ + u128 r; + memcpy(&r.v, bytes, 16); + for (int i = 0; i < 4; ++i) { + r.v[i] = convert_byte_order32(r.v[i]); + } + return r; +} +ENABLE_GCC_WARNING("-Waggregate-return") + +static inline void +u128_to_bytes_ctmul(u128 val, uint8_t *bytes_out) +{ + uint32_t v[4]; + for (int i = 0; i < 4; ++i) { + v[i] = convert_byte_order32(val.v[i]); + } + memcpy(bytes_out, v, 16); +} +static inline void +pv_xor_y_ctmul(polyval_t *pv, u128 val) +{ + for (int i = 0; i < 4; ++i) { + pv->y.v[i] ^= val.v[i]; + } +} +#endif + +struct expanded_key_none {}; +static inline void add_multiple_none(polyval_t *pv, + const uint8_t *input, + const struct expanded_key_none *expanded) +{ + (void) pv; + (void) input; + (void) expanded; +} +static inline void expand_key_none(const polyval_t *inp, + struct expanded_key_none *out) +{ + (void) inp; + (void) out; +} + +/* Kludge: a special value to use for block_stride when we don't support + * processing multiple blocks at once. Previously we used 0, but that + * caused warnings with some comparisons. */ +#define BLOCK_STRIDE_NONE 0xffff + +DISABLE_GCC_WARNING("-Waggregate-return") +#define PV_DECLARE(prefix, \ + st, \ + u128_from_bytes, \ + u128_to_bytes, \ + pv_xor_y, \ + pv_mul_y_h, \ + block_stride, \ + expanded_key_tp, expand_fn, add_multiple_fn) \ + st void \ + prefix ## polyval_key_init(polyval_key_t *pvk, const uint8_t *key) \ + { \ + pvk->h = u128_from_bytes(key); \ + } \ + st void \ + prefix ## polyval_init(polyval_t *pv, const uint8_t *key) \ + { \ + polyval_key_init(&pv->key, key); \ + memset(&pv->y, 0, sizeof(u128)); \ + } \ + st void \ + prefix ## polyval_init_from_key(polyval_t *pv, const polyval_key_t *key) \ + { \ + memcpy(&pv->key, key, sizeof(polyval_key_t)); \ + memset(&pv->y, 0, sizeof(u128)); \ + } \ + st void \ + prefix ## polyval_add_block(polyval_t *pv, const uint8_t *block) \ + { \ + u128 b = u128_from_bytes(block); \ + pv_xor_y(pv, b); \ + pv_mul_y_h(pv); \ + } \ + st void \ + prefix ## polyval_add_zpad(polyval_t *pv, const uint8_t *data, size_t n) \ + { \ + /* since block_stride is a constant, this should get optimized */ \ + if ((block_stride != BLOCK_STRIDE_NONE) \ + && n >= (block_stride) * 16) { \ + expanded_key_tp expanded_key; \ + expand_fn(pv, &expanded_key); \ + while (n >= (block_stride) * 16) { \ + add_multiple_fn(pv, data, &expanded_key); \ + n -= block_stride*16; \ + data += block_stride * 16; \ + } \ + } \ + while (n > 16) { \ + polyval_add_block(pv, data); \ + data += 16; \ + n -= 16; \ + } \ + if (n) { \ + uint8_t block[16]; \ + memset(&block, 0, sizeof(block)); \ + memcpy(block, data, n); \ + polyval_add_block(pv, block); \ + } \ + } \ + st void \ + prefix ## polyval_get_tag(const polyval_t *pv, uint8_t *tag_out) \ + { \ + u128_to_bytes(pv->y, tag_out); \ + } \ + st void \ + prefix ## polyval_reset(polyval_t *pv) \ + { \ + memset(&pv->y, 0, sizeof(u128)); \ + } +ENABLE_GCC_WARNING("-Waggregate-return") + +#ifdef PV_USE_PCLMUL_DETECT +/* We use a boolean to distinguish whether to use the PCLMUL instructions, + * but instead we could use function pointers. It's probably worth + * benchmarking, though it's unlikely to make a measurable difference. + */ +static bool use_pclmul = false; + +/* Declare _both_ variations of our code, statically, + * with different prefixes. */ +DISABLE_GCC_WARNING("-Waggregate-return") +PV_DECLARE(pclmul_, static, + u128_from_bytes_pclmul, + u128_to_bytes_pclmul, + pv_xor_y_pclmul, + pv_mul_y_h_pclmul, + PV_BLOCK_STRIDE, + pv_expanded_key_t, + expand_key_pclmul, + pv_add_multiple_pclmul) + +PV_DECLARE(ctmul64_, static, + u128_from_bytes_ctmul64, + u128_to_bytes_ctmul64, + pv_xor_y_ctmul64, + pv_mul_y_h_ctmul64, + BLOCK_STRIDE_NONE, + struct expanded_key_none, + expand_key_none, + add_multiple_none) +ENABLE_GCC_WARNING("-Waggregate-return") + +void +polyval_key_init(polyval_key_t *pv, const uint8_t *key) +{ + if (use_pclmul) + pclmul_polyval_key_init(pv, key); + else + ctmul64_polyval_key_init(pv, key); +} +void +polyval_init(polyval_t *pv, const uint8_t *key) +{ + if (use_pclmul) + pclmul_polyval_init(pv, key); + else + ctmul64_polyval_init(pv, key); +} +void +polyval_init_from_key(polyval_t *pv, const polyval_key_t *key) +{ + if (use_pclmul) + pclmul_polyval_init_from_key(pv, key); + else + ctmul64_polyval_init_from_key(pv, key); +} +void +polyval_add_block(polyval_t *pv, const uint8_t *block) +{ + if (use_pclmul) + pclmul_polyval_add_block(pv, block); + else + ctmul64_polyval_add_block(pv, block); +} +void +polyval_add_zpad(polyval_t *pv, const uint8_t *data, size_t n) +{ + if (use_pclmul) + pclmul_polyval_add_zpad(pv, data, n); + else + ctmul64_polyval_add_zpad(pv, data, n); +} +void +polyval_get_tag(const polyval_t *pv, uint8_t *tag_out) +{ + if (use_pclmul) + pclmul_polyval_get_tag(pv, tag_out); + else + ctmul64_polyval_get_tag(pv, tag_out); +} +void +polyval_reset(polyval_t *pv) +{ + if (use_pclmul) + pclmul_polyval_reset(pv); + else + ctmul64_polyval_reset(pv); +} + +#elif defined(PV_USE_PCLMUL) +PV_DECLARE(, , + u128_from_bytes_pclmul, + u128_to_bytes_pclmul, + pv_xor_y_pclmul, + pv_mul_y_h_pclmul, + PV_BLOCK_STRIDE, + pv_expanded_key_t, + expand_key_pclmul, + pv_add_multiple_pclmul) +#elif defined(PV_USE_CTMUL64) +PV_DECLARE(, , + u128_from_bytes_ctmul64, + u128_to_bytes_ctmul64, + pv_xor_y_ctmul64, + pv_mul_y_h_ctmul64, + BLOCK_STRIDE_NONE, + struct expanded_key_none, + expand_key_none, + add_multiple_none) + +#elif defined(PV_USE_CTMUL) +DISABLE_GCC_WARNING("-Waggregate-return") +PV_DECLARE(, , u128_from_bytes_ctmul, + u128_to_bytes_ctmul, + pv_xor_y_ctmul, + pv_mul_y_h_ctmul, + BLOCK_STRIDE_NONE, + struct expanded_key_none, + expand_key_none, + add_multiple_none) +ENABLE_GCC_WARNING("-Waggregate-return") +#endif + +#ifdef PV_USE_PCLMUL_DETECT +void +polyval_detect_implementation(void) +{ + unsigned int eax, ebx, ecx, edx; + use_pclmul = false; + if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { + if (0 != (ecx & bit_PCLMUL)) { + use_pclmul = true; + } + } +} +#else +void +polyval_detect_implementation(void) +{ +} +#endif + +#ifdef POLYVAL_USE_EXPANDED_KEYS + +#ifdef PV_USE_PCLMUL_DETECT +#define SHOULD_EXPAND() (use_pclmul) +#else +#define SHOULD_EXPAND() (1) +#endif + +void +polyvalx_init(polyvalx_t *pvx, const uint8_t *key) +{ + polyval_init(&pvx->pv, key); + if (SHOULD_EXPAND()) { + expand_key_pclmul(&pvx->pv, &pvx->expanded); + } +} +void +polyvalx_init_from_key(polyvalx_t *pvx, const polyval_key_t *key) +{ + polyval_init_from_key(&pvx->pv, key); + if (SHOULD_EXPAND()) { + expand_key_pclmul(&pvx->pv, &pvx->expanded); + } +} +void +polyvalx_add_block(polyvalx_t *pvx, const uint8_t *block) +{ + polyval_add_block(&pvx->pv, block); +} +void +polyvalx_add_zpad(polyvalx_t *pvx, const uint8_t *data, size_t n) +{ + if (SHOULD_EXPAND() && n >= PV_BLOCK_STRIDE * 16) { + while (n > PV_BLOCK_STRIDE * 16) { + pv_add_multiple_pclmul(&pvx->pv, data, &pvx->expanded); + data += PV_BLOCK_STRIDE * 16; + n -= PV_BLOCK_STRIDE * 16; + } + } + while (n > 16) { + polyval_add_block(&pvx->pv, data); + data += 16; + n -= 16; + } + if (n) { + uint8_t block[16]; + memset(&block, 0, sizeof(block)); + memcpy(block, data, n); + polyval_add_block(&pvx->pv, block); + } +} +void +polyvalx_get_tag(const polyvalx_t *pvx, uint8_t *tag_out) +{ + polyval_get_tag(&pvx->pv, tag_out); +} +void polyvalx_reset(polyvalx_t *pvx) +{ + polyval_reset(&pvx->pv); +} +#endif + +#if 0 +#include +int +main(int c, char **v) +{ + // From RFC 8452 appendix A + uint8_t key[16] = + { 0x25, 0x62, 0x93, 0x47, 0x58, 0x92, 0x42, 0x76, + 0x1d, 0x31, 0xf8, 0x26, 0xba, 0x4b, 0x75, 0x7b }; + uint8_t block1[16] = + { 0x4f, 0x4f, 0x95, 0x66, 0x8c, 0x83, 0xdf, 0xb6, + 0x40, 0x17, 0x62, 0xbb, 0x2d, 0x01, 0xa2, 0x62 }; + uint8_t block2[16] = { + 0xd1, 0xa2, 0x4d, 0xdd, 0x27, 0x21, 0xd0, 0x06, + 0xbb, 0xe4, 0x5f, 0x20, 0xd3, 0xc9, 0xf3, 0x62 }; + uint8_t expect_result[16] = { + 0xf7, 0xa3, 0xb4, 0x7b, 0x84, 0x61, 0x19, 0xfa, + 0xe5, 0xb7, 0x86, 0x6c, 0xf5, 0xe5, 0xb7, 0x7e }; + + polyval_t pv; + uint8_t tag[16]; + polyval_init(&pv, key); + polyval_add_block(&pv, block1); + polyval_add_block(&pv, block2); + polyval_get_tag(&pv, tag); + if (!memcmp(expect_result, tag, 16)) { + puts("OK"); + return 0; + } else { + puts("NOPE"); + return 1; + } +} +#endif diff -Nru tor-0.4.8.16/src/ext/polyval/polyval.h tor-0.4.9.6/src/ext/polyval/polyval.h --- tor-0.4.8.16/src/ext/polyval/polyval.h 1970-01-01 00:00:00.000000000 +0000 +++ tor-0.4.9.6/src/ext/polyval/polyval.h 2026-03-25 14:30:34.000000000 +0000 @@ -0,0 +1,185 @@ +/* Copyright (c) 2025, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file polyval.h + * \brief APIs for polyval universal hash function. + **/ + +#ifndef TOR_POLYVAL_H +#define TOR_POLYVAL_H + +#include "orconfig.h" +#include "lib/cc/torint.h" + +/* Decide which implementation to use. */ +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) \ + || defined(_M_X64) || defined(_M_IX86) || defined(__i486) \ + || defined(__i386__) +#define PV_INTEL_ARCH +#endif + +#if defined(PV_INTEL_ARCH) && defined(__PCLMUL__) +/* We're building for an architecture that always has the intel + * intrinsics for carryless multiply. + * No need for runtime detection. + */ +#define PV_USE_PCLMUL_UNCONDITIONAL +#define PCLMUL_ANY + +#elif defined(PV_INTEL_ARCH) && SIZEOF_VOID_P >= 8 +/* We _might_ have PCLMUL, or we might not. + * We need to detect it at runtime. + */ +#define PV_USE_PCLMUL_DETECT +#define PCLMUL_ANY + +#elif SIZEOF_VOID_P >= 8 +/* It's a 64-bit architecture; use the generic 64-bit constant-time + * implementation. + */ +#define PV_USE_CTMUL64 +#elif SIZEOF_VOID_P == 4 +/* It's a 64-bit architecture; use the generic 32-bit constant-time + * implementation. + */ +#define PV_USE_CTMUL +#else +#error "sizeof(void*) is implausibly weird." +#endif + +#ifdef PCLMUL_ANY +#include + +#define POLYVAL_USE_EXPANDED_KEYS +#endif + +/** + * Declare a 128 bit integer type. + # The exact representation will depend on which implementation we've chosen. + */ +#if defined(PV_USE_PCLMUL_UNCONDITIONAL) +typedef __m128i pv_u128_; +#elif defined(PV_USE_PCLMUL_DETECT) +typedef union pv_u128_ { + __m128i u128x1; + struct { + uint64_t lo; + uint64_t hi; + } u64x2; +} pv_u128_; +#elif defined(PV_USE_CTMUL64) +typedef struct pv_u128_ { + uint64_t lo; + uint64_t hi; +} pv_u128_; +#elif defined(PV_USE_CTMUL) +typedef struct pv_u128_ { + uint32_t v[4]; +} pv_u128_; +#endif + +/** A key for a polyval hash, plus any precomputed key material. */ +typedef struct polyval_key_t { + pv_u128_ h; +} polyval_key_t; + +/** + * State for an instance of the polyval hash. + **/ +typedef struct polyval_t { + /** The key used for this instance of polyval. */ + polyval_key_t key; + /** The accumulator */ + pv_u128_ y; +} polyval_t; + +/** + * Length of a polyval key, in bytes. + */ +#define POLYVAL_KEY_LEN 16 +/** + * Length of a polyval block, in bytes. + */ +#define POLYVAL_BLOCK_LEN 16 +/** + * Length of a polyval tag (output), in bytes. + */ +#define POLYVAL_TAG_LEN 16 + +/** Do any necessary precomputation from a polyval key, + * and store it. + */ +void polyval_key_init(polyval_key_t *, const uint8_t *key); +/** + * Initialize a polyval instance with a given key. + */ +void polyval_init(polyval_t *, const uint8_t *key); +/** + * Initialize a polyval instance with a preconstructed key. + */ +void polyval_init_from_key(polyval_t *, const polyval_key_t *key); +/** + * Update a polyval instance with a new 16-byte block. + */ +void polyval_add_block(polyval_t *, const uint8_t *block); +/** + * Update a polyval instance with 'n' bytes from 'data'. + * If 'n' is not evenly divisible by 16, pad it at the end with zeros. + * + * NOTE: This is not a general-purpose padding construction; + * it can be insecure if your are using it in context where the input length + * is variable. + */ +void polyval_add_zpad(polyval_t *, const uint8_t *data, size_t n); +/** + * Copy the 16-byte tag from a polyval instance into 'tag_out' + */ +void polyval_get_tag(const polyval_t *, uint8_t *tag_out); +/** + * Reset a polyval instance to its original state, + * retaining its key. + */ +void polyval_reset(polyval_t *); + +/** If a faster-than-default polyval implementation is available, use it. */ +void polyval_detect_implementation(void); + +#ifdef POLYVAL_USE_EXPANDED_KEYS +/* These variations are as for polyval_\*, but they use pre-expanded keys. + * They're appropriate when you know a key is likely to get used more than once + * on a large input. + */ + +/** How many blocks to handle at once with an expanded key */ +#define PV_BLOCK_STRIDE 8 +typedef struct pv_expanded_key_t { + // powers of h in reverse order, down to 2. + // (in other words, contains + // h^PCLMUL_BLOCK_STRIDE .. H^2) + __m128i k[PV_BLOCK_STRIDE-1]; +} pv_expanded_key_t; +typedef struct polyvalx_t { + polyval_t pv; + pv_expanded_key_t expanded; +} polyvalx_t; + +void polyvalx_init(polyvalx_t *, const uint8_t *key); +void polyvalx_init_from_key(polyvalx_t *, const polyval_key_t *key); +void polyvalx_add_block(polyvalx_t *, const uint8_t *block); +void polyvalx_add_zpad(polyvalx_t *, const uint8_t *data, size_t n); +void polyvalx_get_tag(const polyvalx_t *, uint8_t *tag_out); +void polyvalx_reset(polyvalx_t *); + +#else +#define polyvalx_t polyval_t +#define polyvalx_key_init polyval_key_init +#define polyvalx_init polyval_init +#define polyvalx_init_from_key polyval_init_from_key +#define polyvalx_add_block polyval_add_block +#define polyvalx_add_zpad polyval_add_zpad +#define polyvalx_get_tag polyval_get_tag +#define polyvalx_reset polyval_reset +#endif + +#endif diff -Nru tor-0.4.8.16/src/feature/client/bridges.c tor-0.4.9.6/src/feature/client/bridges.c --- tor-0.4.8.16/src/feature/client/bridges.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/client/bridges.c 2026-03-25 14:30:34.000000000 +0000 @@ -316,7 +316,8 @@ /** If we have a bridge configured whose digest matches * ei->identity_digest, or a bridge with no known digest whose address * matches ei->addr:ei->port, return 1. Else return 0. - * If ei->onion_key is NULL, check for address/port matches only. + * If ei has no onion key configured, check for address/port matches + * only. * * Note that if the extend_info_t contains multiple addresses, we return true * only if _every_ address is a bridge. @@ -324,7 +325,8 @@ int extend_info_is_a_configured_bridge(const extend_info_t *ei) { - const char *digest = ei->onion_key ? ei->identity_digest : NULL; + const char *digest = curve25519_public_key_is_ok(&ei->curve25519_onion_key) + ? ei->identity_digest : NULL; const tor_addr_port_t *ap1 = NULL, *ap2 = NULL; if (! tor_addr_is_null(&ei->orports[0].addr)) ap1 = &ei->orports[0]; diff -Nru tor-0.4.8.16/src/feature/client/circpathbias.c tor-0.4.9.6/src/feature/client/circpathbias.c --- tor-0.4.8.16/src/feature/client/circpathbias.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/client/circpathbias.c 2026-03-25 14:30:34.000000000 +0000 @@ -34,10 +34,10 @@ #include "feature/client/entrynodes.h" #include "feature/nodelist/networkstatus.h" #include "core/or/relay.h" +#include "core/or/relay_msg.h" #include "lib/math/fp.h" #include "lib/math/laplace.h" -#include "core/or/cell_st.h" #include "core/or/cpath_build_state_st.h" #include "core/or/crypt_path_st.h" #include "core/or/extend_info_st.h" @@ -798,7 +798,7 @@ pathbias_send_usable_probe(circuit_t *circ) { /* Based on connection_ap_handshake_send_begin() */ - char payload[CELL_PAYLOAD_SIZE]; + char payload[RELAY_PAYLOAD_SIZE_MAX]; int payload_len; origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); crypt_path_t *cpath_layer = NULL; @@ -853,7 +853,7 @@ return -1; } - tor_snprintf(payload,RELAY_PAYLOAD_SIZE, "%s:25", probe_nonce); + tor_snprintf(payload,RELAY_PAYLOAD_SIZE_MAX, "%s:25", probe_nonce); payload_len = (int)strlen(payload)+1; // XXX: need this? Can we assume ipv4 will always be supported? @@ -903,41 +903,37 @@ * If the response is valid, return 0. Otherwise return < 0. */ int -pathbias_check_probe_response(circuit_t *circ, const cell_t *cell) +pathbias_check_probe_response(circuit_t *circ, const relay_msg_t *msg) { /* Based on connection_edge_process_relay_cell() */ - relay_header_t rh; int reason; uint32_t ipv4_host; origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); - tor_assert(cell); + tor_assert(msg); tor_assert(ocirc); tor_assert(circ->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING); - relay_header_unpack(&rh, cell->payload); + reason = msg->length > 0 ? get_uint8(msg->body) : END_STREAM_REASON_MISC; - reason = rh.length > 0 ? - get_uint8(cell->payload+RELAY_HEADER_SIZE) : END_STREAM_REASON_MISC; - - if (rh.command == RELAY_COMMAND_END && + if (msg->command == RELAY_COMMAND_END && reason == END_STREAM_REASON_EXITPOLICY && - ocirc->pathbias_probe_id == rh.stream_id) { + ocirc->pathbias_probe_id == msg->stream_id) { /* Check length+extract host: It is in network order after the reason code. * See connection_edge_end(). */ - if (rh.length < 9) { /* reason+ipv4+dns_ttl */ + if (msg->length < 9) { /* reason+ipv4+dns_ttl */ log_notice(LD_PROTOCOL, - "Short path bias probe response length field (%d).", rh.length); + "Short path bias probe response length field (%d).", msg->length); return - END_CIRC_REASON_TORPROTOCOL; } - ipv4_host = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+1)); + ipv4_host = ntohl(get_uint32(msg->body + 1)); /* Check nonce */ if (ipv4_host == ocirc->pathbias_probe_nonce) { pathbias_mark_use_success(ocirc); - circuit_read_valid_data(ocirc, rh.length); + circuit_read_valid_data(ocirc, msg->length); circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); log_info(LD_CIRC, "Got valid path bias probe back for circ %d, stream %d.", @@ -954,7 +950,7 @@ log_info(LD_CIRC, "Got another cell back back on pathbias probe circuit %d: " "Command: %d, Reason: %d, Stream-id: %d", - ocirc->global_identifier, rh.command, reason, rh.stream_id); + ocirc->global_identifier, msg->command, reason, msg->stream_id); return -1; } @@ -963,58 +959,54 @@ * and if so, count it as valid. */ void -pathbias_count_valid_cells(circuit_t *circ, const cell_t *cell) +pathbias_count_valid_cells(circuit_t *circ, const relay_msg_t *msg) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); - relay_header_t rh; - - relay_header_unpack(&rh, cell->payload); /* Check to see if this is a cell from a previous connection, * or is a request to close the circuit. */ - switch (rh.command) { + switch (msg->command) { case RELAY_COMMAND_TRUNCATED: /* Truncated cells can arrive on path bias circs. When they do, * just process them. This closes the circ, but it was junk anyway. * No reason to wait for the probe. */ - circuit_read_valid_data(ocirc, rh.length); - circuit_truncated(TO_ORIGIN_CIRCUIT(circ), - get_uint8(cell->payload + RELAY_HEADER_SIZE)); + circuit_read_valid_data(ocirc, msg->length); + circuit_truncated(TO_ORIGIN_CIRCUIT(circ), get_uint8(msg->body)); break; case RELAY_COMMAND_END: if (connection_half_edge_is_valid_end(ocirc->half_streams, - rh.stream_id)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length); + msg->stream_id)) { + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } break; case RELAY_COMMAND_DATA: if (connection_half_edge_is_valid_data(ocirc->half_streams, - rh.stream_id)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length); + msg->stream_id)) { + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } break; case RELAY_COMMAND_SENDME: if (connection_half_edge_is_valid_sendme(ocirc->half_streams, - rh.stream_id)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length); + msg->stream_id)) { + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } break; case RELAY_COMMAND_CONNECTED: if (connection_half_edge_is_valid_connected(ocirc->half_streams, - rh.stream_id)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length); + msg->stream_id)) { + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } break; case RELAY_COMMAND_RESOLVED: if (connection_half_edge_is_valid_resolved(ocirc->half_streams, - rh.stream_id)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length); + msg->stream_id)) { + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } break; } diff -Nru tor-0.4.8.16/src/feature/client/circpathbias.h tor-0.4.9.6/src/feature/client/circpathbias.h --- tor-0.4.8.16/src/feature/client/circpathbias.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/client/circpathbias.h 2026-03-25 14:30:34.000000000 +0000 @@ -12,6 +12,8 @@ #ifndef TOR_CIRCPATHBIAS_H #define TOR_CIRCPATHBIAS_H +#include "core/or/relay_msg_st.h" + double pathbias_get_extreme_rate(const or_options_t *options); double pathbias_get_extreme_use_rate(const or_options_t *options); int pathbias_get_dropguards(const or_options_t *options); @@ -19,8 +21,8 @@ void pathbias_count_build_success(origin_circuit_t *circ); int pathbias_count_build_attempt(origin_circuit_t *circ); int pathbias_check_close(origin_circuit_t *circ, int reason); -int pathbias_check_probe_response(circuit_t *circ, const cell_t *cell); -void pathbias_count_valid_cells(circuit_t *circ, const cell_t *cell); +int pathbias_check_probe_response(circuit_t *circ, const relay_msg_t *msg); +void pathbias_count_valid_cells(circuit_t *circ, const relay_msg_t *msg); void pathbias_count_use_attempt(origin_circuit_t *circ); void pathbias_mark_use_success(origin_circuit_t *circ); void pathbias_mark_use_rollback(origin_circuit_t *circ); diff -Nru tor-0.4.8.16/src/feature/client/dnsserv.c tor-0.4.9.6/src/feature/client/dnsserv.c --- tor-0.4.8.16/src/feature/client/dnsserv.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/client/dnsserv.c 2026-03-25 14:30:34.000000000 +0000 @@ -319,6 +319,7 @@ break; case RESOLVED_TYPE_ERROR: case RESOLVED_TYPE_ERROR_TRANSIENT: + case RESOLVED_TYPE_NOERROR: /* Addr doesn't matter, since we're not sending it back in the reply.*/ return addr; default: @@ -379,6 +380,8 @@ tor_free(ans); } else if (answer_type == RESOLVED_TYPE_ERROR) { err = DNS_ERR_NOTEXIST; + } else if (answer_type == RESOLVED_TYPE_NOERROR) { + err = DNS_ERR_NONE; } else { /* answer_type == RESOLVED_TYPE_ERROR_TRANSIENT */ err = DNS_ERR_SERVERFAILED; } diff -Nru tor-0.4.8.16/src/feature/client/entrynodes.c tor-0.4.9.6/src/feature/client/entrynodes.c --- tor-0.4.8.16/src/feature/client/entrynodes.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/client/entrynodes.c 2026-03-25 14:30:34.000000000 +0000 @@ -1595,13 +1595,15 @@ /* Allocate and return a new exit guard restriction that excludes all current * and pending conflux guards */ STATIC entry_guard_restriction_t * -guard_create_conflux_restriction(const origin_circuit_t *circ) +guard_create_conflux_restriction(const origin_circuit_t *circ, + const uint8_t *exit_id) { entry_guard_restriction_t *rst = NULL; rst = tor_malloc_zero(sizeof(entry_guard_restriction_t)); rst->type = RST_EXCL_LIST; rst->excluded = smartlist_new(); conflux_add_guards_to_exclude_list(circ, rst->excluded); + memcpy(rst->exclude_id, exit_id, DIGEST_LEN); return rst; } @@ -1653,7 +1655,8 @@ guard_obeys_exit_restriction(const entry_guard_t *guard, const entry_guard_restriction_t *rst) { - tor_assert(rst->type == RST_EXIT_NODE); + tor_assert(rst->type == RST_EXIT_NODE || + rst->type == RST_EXCL_LIST); // Exclude the exit ID and all of its family. const node_t *node = node_get_by_id((const char*)rst->exclude_id); @@ -1709,7 +1712,8 @@ } else if (rst->type == RST_OUTDATED_MD_DIRSERVER) { return guard_obeys_md_dirserver_restriction(guard); } else if (rst->type == RST_EXCL_LIST) { - return !smartlist_contains_digest(rst->excluded, guard->identity); + return guard_obeys_exit_restriction(guard, rst) && + !smartlist_contains_digest(rst->excluded, guard->identity); } tor_assert_nonfatal_unreached(); @@ -2169,7 +2173,7 @@ static ratelim_t guardlog = RATELIM_INIT(60); log_fn_ratelim(&guardlog, LOG_NOTICE, LD_GUARD, "All current guards excluded by path restriction " - "type %d; using an additonal guard.", + "type %d; using an additional guard.", rst->type); } else { break; @@ -3875,8 +3879,9 @@ entry_guard_restriction_t *rst = NULL; /* If we this is a conflux circuit, build an exclusion list for it. */ - if (CIRCUIT_IS_CONFLUX(TO_CIRCUIT(circ))) { - rst = guard_create_conflux_restriction(circ); + if (CIRCUIT_IS_CONFLUX(TO_CIRCUIT(circ)) && state + && (exit_id = build_state_get_exit_rsa_id(state))) { + rst = guard_create_conflux_restriction(circ, exit_id); /* Don't allow connecting back to the exit if there is one */ if (state && (exit_id = build_state_get_exit_rsa_id(state))) { /* add the exit_id to the excluded list */ diff -Nru tor-0.4.8.16/src/feature/client/entrynodes.h tor-0.4.9.6/src/feature/client/entrynodes.h --- tor-0.4.8.16/src/feature/client/entrynodes.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/client/entrynodes.h 2026-03-25 14:30:34.000000000 +0000 @@ -605,7 +605,7 @@ STATIC entry_guard_restriction_t *guard_create_dirserver_md_restriction(void); STATIC entry_guard_restriction_t * guard_create_conflux_restriction( - const origin_circuit_t *circ); + const origin_circuit_t *circ, const uint8_t *exit_id); STATIC void entry_guard_restriction_free_(entry_guard_restriction_t *rst); #define entry_guard_restriction_free(rst) \ diff -Nru tor-0.4.8.16/src/feature/client/include.am tor-0.4.9.6/src/feature/client/include.am --- tor-0.4.8.16/src/feature/client/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/client/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -1,6 +1,6 @@ # ADD_C_FILE: INSERT SOURCES HERE. -LIBTOR_APP_A_SOURCES += \ +LIBTOR_APP_A_SOURCES += \ src/feature/client/addressmap.c \ src/feature/client/bridges.c \ src/feature/client/circpathbias.c \ diff -Nru tor-0.4.8.16/src/feature/client/transports.c tor-0.4.9.6/src/feature/client/transports.c --- tor-0.4.8.16/src/feature/client/transports.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/client/transports.c 2026-03-25 14:30:34.000000000 +0000 @@ -90,12 +90,14 @@ **/ #include "lib/string/printf.h" +#include "lib/evloop/compat_libevent.h" #define PT_PRIVATE #include "core/or/or.h" #include "feature/client/bridges.h" #include "app/config/config.h" #include "core/mainloop/connection.h" #include "core/or/circuitbuild.h" +#include "feature/hibernate/hibernate.h" #include "feature/client/transports.h" #include "feature/relay/router.h" #include "feature/relay/relay_find_addr.h" @@ -492,7 +494,9 @@ launched: */ tor_assert(smartlist_len(mp->transports_to_launch) > 0); - tor_assert(mp->conf_state == PT_PROTO_COMPLETED); + if (BUG(mp->conf_state != PT_PROTO_COMPLETED)) { + goto needs_restart; + } if (smartlist_len(mp->transports_to_launch) != smartlist_len(mp->transports)) goto needs_restart; @@ -517,11 +521,20 @@ { transport_t *t_tmp = NULL; - tor_assert(mp->conf_state == PT_PROTO_COMPLETED); + /* Rate limit this log as a regurlarly dying PT would log this once every + * second (retry time). Every 5 minutes is likely loud enough to notice. */ + static ratelim_t log_died_lim = RATELIM_INIT(300); + log_fn_ratelim(&log_died_lim, LOG_WARN, LD_PT, + "Managed proxy at '%s' died in state %s", mp->argv[0], + managed_proxy_state_to_string(mp->conf_state)); /* destroy the process handle and terminate the process. */ if (mp->process) { process_set_data(mp->process, NULL); + if (we_are_shutting_down()) + log_notice(LD_CONFIG, "Managed proxy \"%s\" having PID %" PRIu64 " " + "is being terminated...", mp->argv[0], + process_get_pid(mp->process)); process_terminate(mp->process); } @@ -543,9 +556,11 @@ mp->proxy_uri = get_pt_proxy_uri(); mp->proxy_supported = 0; + if (mp->conf_state == PT_PROTO_COMPLETED) + unconfigured_proxies_n++; + /* flag it as an infant proxy so that it gets launched on next tick */ managed_proxy_set_state(mp, PT_PROTO_INFANT); - unconfigured_proxies_n++; } /** Launch managed proxy mp. */ @@ -643,6 +658,25 @@ mark_my_descriptor_dirty("configured managed proxies"); } +/** event callback to launch managed proxy after a delay */ +STATIC void +launch_proxy_ev(mainloop_event_t *event, void *v) +{ + managed_proxy_t *mp = v; + + (void) event; + + tor_assert(mp); + if (BUG(mp->conf_state != PT_PROTO_WAITING)) { + return; + } + + if (launch_managed_proxy(mp) < 0) { /* launch fail */ + managed_proxy_set_state(mp, PT_PROTO_FAILED_LAUNCH); + handle_finished_proxy(mp); + } +} + /** Attempt to continue configuring managed proxy mp. * Return 1 if the transport configuration finished, and return 0 * otherwise (if we still have more configuring to do for this @@ -652,10 +686,13 @@ { /* if we haven't launched the proxy yet, do it now */ if (mp->conf_state == PT_PROTO_INFANT) { - if (launch_managed_proxy(mp) < 0) { /* launch fail */ - managed_proxy_set_state(mp, PT_PROTO_FAILED_LAUNCH); - handle_finished_proxy(mp); + const struct timeval delay_tv = { 1, 0 }; + if (!mp->process_launch_ev) { + mp->process_launch_ev = mainloop_event_new(launch_proxy_ev, mp); } + mainloop_event_schedule(mp->process_launch_ev, &delay_tv); + managed_proxy_set_state(mp, PT_PROTO_WAITING); + return 0; } @@ -676,6 +713,7 @@ t->name, fmt_addrport(&t->addr, t->port)); control_event_transport_launched("server", t->name, &t->addr, t->port); } SMARTLIST_FOREACH_END(t); + pt_update_bridge_lines(); } /** Register all the transports supported by client managed proxy @@ -755,6 +793,9 @@ process_terminate(mp->process); } + if (mp->process_launch_ev) + mainloop_event_free(mp->process_launch_ev); + tor_free(mp); } @@ -827,6 +868,7 @@ managed_proxy_set_state(mp, PT_PROTO_COMPLETED); break; case PT_PROTO_INFANT: + case PT_PROTO_WAITING: case PT_PROTO_LAUNCHED: case PT_PROTO_ACCEPTING_METHODS: case PT_PROTO_COMPLETED: @@ -1830,6 +1872,92 @@ return the_string; } +/** Log the bridge lines that clients can use to connect. */ +void +pt_update_bridge_lines(void) +{ + char fingerprint[FINGERPRINT_LEN+1]; + smartlist_t *string_chunks = NULL; + + if (!server_identity_key_is_set() || !managed_proxy_list) + return; + + if (crypto_pk_get_fingerprint(get_server_identity_key(), fingerprint, 0)<0) { + log_err(LD_BUG, "Error computing fingerprint"); + return; + } + + string_chunks = smartlist_new(); + + SMARTLIST_FOREACH_BEGIN(managed_proxy_list, const managed_proxy_t *, mp) { + if (!mp->is_server) + continue; + + tor_assert(mp->transports); + + SMARTLIST_FOREACH_BEGIN(mp->transports, const transport_t *, t) { + char *transport_args = NULL; + const char *saddr = NULL; + + /* If the transport proxy returned "0.0.0.0" as its address, display + * our external address if we know it, or a placeholder if we don't */ + if (tor_addr_is_null(&t->addr)) { + tor_addr_t addr; + /* Attempt to find the IPv4 and then attempt to find the IPv6 if we + * can't find it. */ + bool found = relay_find_addr_to_publish(get_options(), AF_INET, + RELAY_FIND_ADDR_NO_FLAG, + &addr); + if (!found) { + found = relay_find_addr_to_publish(get_options(), AF_INET6, + RELAY_FIND_ADDR_NO_FLAG, &addr); + } + if (found && !tor_addr_is_null(&addr)) { + saddr = fmt_and_decorate_addr(&addr); + } else { + saddr = ""; + } + } else { + saddr = fmt_and_decorate_addr(&t->addr); + } + + /* If this transport has any arguments with it, prepend a space + * to them so that we can add them to the transport line, and replace + * commas with spaces to make it a valid bridge line. */ + if (t->extra_info_args) { + tor_asprintf(&transport_args, " %s", t->extra_info_args); + for (int i = 0; transport_args[i]; i++) { + if (transport_args[i] == ',') { + transport_args[i] = ' '; + } + } + } + + smartlist_add_asprintf(string_chunks, "Bridge %s %s:%d %s%s", + t->name, saddr, t->port, fingerprint, + transport_args ? transport_args : ""); + tor_free(transport_args); + } SMARTLIST_FOREACH_END(t); + } SMARTLIST_FOREACH_END(mp); + + /* If we have any valid bridgelines, join them into a single string, and + * save them to disk. Don't create an empty file. */ + if (smartlist_len(string_chunks) != 0) { + char *str = smartlist_join_strings(string_chunks, "\n", 1, NULL); + char *fname = get_datadir_fname("bridgelines"); + if (write_str_to_file_if_not_equal(fname, str)) { + log_warn(LD_FS, "Couldn't save bridge lines to disk"); + } else { + log_info(LD_FS, "Saved bridge lines to disk"); + } + tor_free(fname); + tor_free(str); + } + + SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s)); + smartlist_free(string_chunks); +} + /** Stringify the SOCKS arguments in socks_args according to * 180_pluggable_transport.txt. The string is allocated on the heap * and it's the responsibility of the caller to free it after use. */ @@ -2021,9 +2149,13 @@ managed_proxy_t *mp = process_get_data(process); const char *name = mp ? mp->argv[0] : "N/A"; - log_warn(LD_PT, - "Managed proxy \"%s\" process terminated with status code %" PRIu64, - name, exit_code); + if (!we_are_shutting_down()) + log_warn(LD_PT, "Managed proxy \"%s\" having PID %" PRIu64 " " + "terminated with status code %" PRIu64, + name, process_get_pid(process), exit_code); + else + log_notice(LD_PT, "Managed proxy \"%s\" having PID %" PRIu64 " " + "has exited.", name, process_get_pid(process)); if (mp) { /* We remove this process_t from the mp. */ @@ -2033,8 +2165,10 @@ /* Prepare the proxy for restart. */ proxy_prepare_for_restart(mp); - /* We have proxies we want to restart? */ - pt_configure_remaining_proxies(); + if (!we_are_shutting_down()) { + /* We have proxies we want to restart? */ + pt_configure_remaining_proxies(); + } } /* Returning true here means that the process subsystem will take care of @@ -2118,6 +2252,8 @@ switch (state) { case PT_PROTO_INFANT: return "Infant"; + case PT_PROTO_WAITING: + return "Waiting"; case PT_PROTO_LAUNCHED: return "Launched"; case PT_PROTO_ACCEPTING_METHODS: diff -Nru tor-0.4.8.16/src/feature/client/transports.h tor-0.4.9.6/src/feature/client/transports.h --- tor-0.4.8.16/src/feature/client/transports.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/client/transports.h 2026-03-25 14:30:34.000000000 +0000 @@ -57,6 +57,7 @@ int pt_proxies_configuration_pending(void); char *pt_get_extra_info_descriptor_string(void); +void pt_update_bridge_lines(void); void pt_free_all(void); @@ -76,6 +77,7 @@ /** State of the managed proxy configuration protocol. */ enum pt_proto_state { PT_PROTO_INFANT, /* was just born */ + PT_PROTO_WAITING, /* waiting to be launched */ PT_PROTO_LAUNCHED, /* was just launched */ PT_PROTO_ACCEPTING_METHODS, /* accepting methods */ PT_PROTO_CONFIGURED, /* configured successfully */ @@ -100,6 +102,9 @@ /* A pointer to the process of this managed proxy. */ struct process_t *process; + /* timer event to launch proxy */ + struct mainloop_event_t *process_launch_ev; + /** Boolean: We are re-parsing our config, and we are going to * remove this managed proxy if we don't find it any transport * plugins that use it. */ @@ -149,6 +154,7 @@ STATIC managed_proxy_t *managed_proxy_create(const smartlist_t *transport_list, char **proxy_argv, int is_server); +STATIC void launch_proxy_ev(struct mainloop_event_t *event, void *v); STATIC int configure_proxy(managed_proxy_t *mp); STATIC char* get_pt_proxy_uri(void); diff -Nru tor-0.4.8.16/src/feature/control/btrack_orconn_cevent.c tor-0.4.9.6/src/feature/control/btrack_orconn_cevent.c --- tor-0.4.8.16/src/feature/control/btrack_orconn_cevent.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/control/btrack_orconn_cevent.c 2026-03-25 14:30:34.000000000 +0000 @@ -86,8 +86,6 @@ case OR_CONN_STATE_TLS_HANDSHAKING: control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DONE, 0); break; - case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING: - case OR_CONN_STATE_OR_HANDSHAKING_V2: case OR_CONN_STATE_OR_HANDSHAKING_V3: control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0); break; @@ -140,8 +138,6 @@ case OR_CONN_STATE_TLS_HANDSHAKING: control_event_bootstrap(BOOTSTRAP_STATUS_AP_CONN_DONE, 0); break; - case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING: - case OR_CONN_STATE_OR_HANDSHAKING_V2: case OR_CONN_STATE_OR_HANDSHAKING_V3: control_event_bootstrap(BOOTSTRAP_STATUS_AP_HANDSHAKE, 0); break; diff -Nru tor-0.4.8.16/src/feature/control/control.c tor-0.4.9.6/src/feature/control/control.c --- tor-0.4.8.16/src/feature/control/control.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/control/control.c 2026-03-25 14:30:34.000000000 +0000 @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2021, The Tor Project, Inc. */ + * Copyright (c) 2007-2024, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -252,6 +252,8 @@ if (conn->is_owning_control_connection) { lost_owning_controller("connection", "closed"); } + + control_remove_authenticated_connection(conn); } /** Return true iff cmd is allowable (or at least forgivable) at this diff -Nru tor-0.4.8.16/src/feature/control/control_auth.c tor-0.4.9.6/src/feature/control/control_auth.c --- tor-0.4.8.16/src/feature/control/control_auth.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/control/control_auth.c 2026-03-25 14:30:34.000000000 +0000 @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2021, The Tor Project, Inc. */ + * Copyright (c) 2007-2024, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -11,6 +11,7 @@ #include "app/config/config.h" #include "core/mainloop/connection.h" #include "feature/control/control.h" +#include "feature/control/control_events.h" #include "feature/control/control_cmd.h" #include "feature/control/control_auth.h" #include "feature/control/control_cmd_args_st.h" @@ -24,6 +25,36 @@ #include "lib/crypt_ops/crypto_s2k.h" +/* List of authenticated control connections */ +static smartlist_t *control_auth_conns = NULL; + +static void +control_add_authenticated_connection(control_connection_t *conn) +{ + if (!control_auth_conns) + control_auth_conns = smartlist_new(); + + smartlist_add(control_auth_conns, conn); + + if (smartlist_len(control_auth_conns) == 1) + stats_init(); +} + +void +control_remove_authenticated_connection(const control_connection_t *conn) +{ + if (!control_auth_conns) + return; + + smartlist_remove(control_auth_conns, conn); + + if (smartlist_len(control_auth_conns) == 0) { + smartlist_free(control_auth_conns); + control_auth_conns = NULL; + stats_clear(); + } +} + /** If we're using cookie-type authentication, how long should our cookies be? */ #define AUTHENTICATION_COOKIE_LEN 32 @@ -429,6 +460,9 @@ SMARTLIST_FOREACH(sl, char *, str, tor_free(str)); smartlist_free(sl); } + + control_add_authenticated_connection(conn); + return 0; } @@ -438,4 +472,7 @@ if (authentication_cookie) /* Free the auth cookie */ tor_free(authentication_cookie); authentication_cookie_is_set = 0; + + if (control_auth_conns) + smartlist_free(control_auth_conns); } diff -Nru tor-0.4.8.16/src/feature/control/control_auth.h tor-0.4.9.6/src/feature/control/control_auth.h --- tor-0.4.8.16/src/feature/control/control_auth.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/control/control_auth.h 2026-03-25 14:30:34.000000000 +0000 @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2021, The Tor Project, Inc. */ + * Copyright (c) 2007-2024, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -12,6 +12,8 @@ #ifndef TOR_CONTROL_AUTH_H #define TOR_CONTROL_AUTH_H +void control_remove_authenticated_connection(const control_connection_t *conn); + struct control_cmd_args_t; struct control_cmd_syntax_t; diff -Nru tor-0.4.8.16/src/feature/control/control_cmd.c tor-0.4.9.6/src/feature/control/control_cmd.c --- tor-0.4.8.16/src/feature/control/control_cmd.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/control/control_cmd.c 2026-03-25 14:30:34.000000000 +0000 @@ -32,6 +32,7 @@ #include "feature/control/control_events.h" #include "feature/control/control_getinfo.h" #include "feature/control/control_proto.h" +#include "feature/hs/hs_config.h" #include "feature/hs/hs_control.h" #include "feature/hs/hs_service.h" #include "feature/nodelist/nodelist.h" @@ -1578,6 +1579,9 @@ add_onion_secret_key_t *pk, smartlist_t *port_cfgs, int max_streams, int max_streams_close_circuit, + int pow_defenses_enabled, + uint32_t pow_queue_rate, + uint32_t pow_queue_burst, smartlist_t *auth_clients_v3, char **address_out) { hs_service_add_ephemeral_status_t ret; @@ -1590,6 +1594,9 @@ case HS_VERSION_THREE: ret = hs_service_add_ephemeral(pk->v3, port_cfgs, max_streams, max_streams_close_circuit, + pow_defenses_enabled, + pow_queue_rate, + pow_queue_burst, auth_clients_v3, address_out); break; default: @@ -1614,7 +1621,15 @@ } static const char *add_onion_keywords[] = { - "Port", "Flags", "MaxStreams", "ClientAuth", "ClientAuthV3", NULL + "Port", + "Flags", + "MaxStreams", + "PoWDefensesEnabled", + "PoWQueueRate", + "PoWQueueBurst", + "ClientAuth", + "ClientAuthV3", + NULL }; static const control_cmd_syntax_t add_onion_syntax = { .min_args = 1, .max_args = 1, @@ -1641,6 +1656,9 @@ int max_streams = 0; int max_streams_close_circuit = 0; int non_anonymous = 0; + int pow_defenses_enabled = HS_CONFIG_V3_POW_DEFENSES_DEFAULT; + uint32_t pow_queue_rate = HS_CONFIG_V3_POW_QUEUE_RATE; + uint32_t pow_queue_burst = HS_CONFIG_V3_POW_QUEUE_BURST; const config_line_t *arg; for (arg = args->kwargs; arg; arg = arg->next) { @@ -1660,6 +1678,30 @@ control_write_endreply(conn, 512, "Invalid MaxStreams"); goto out; } + } else if (!strcasecmp(arg->key, "PoWDefensesEnabled")) { + int ok = 0; + pow_defenses_enabled = (int)tor_parse_long(arg->value, 10, + 0, 1, &ok, NULL); + if (!ok) { + control_write_endreply(conn, 512, "Invalid PoWDefensesEnabled"); + goto out; + } + } else if (!strcasecmp(arg->key, "PoWQueueRate")) { + int ok = 0; + pow_queue_rate = (uint32_t)tor_parse_ulong(arg->value, 10, + 0, UINT32_MAX, &ok, NULL); + if (!ok) { + control_write_endreply(conn, 512, "Invalid PoWQueueRate"); + goto out; + } + } else if (!strcasecmp(arg->key, "PoWQueueBurst")) { + int ok = 0; + pow_queue_burst = (uint32_t)tor_parse_ulong(arg->value, 10, + 0, UINT32_MAX, &ok, NULL); + if (!ok) { + control_write_endreply(conn, 512, "Invalid PoWQueueBurst"); + goto out; + } } else if (!strcasecmp(arg->key, "Flags")) { /* "Flags=Flag[,Flag]", where Flag can be: * * 'DiscardPK' - If tor generates the keypair, do not include it in @@ -1775,6 +1817,9 @@ int ret = add_onion_helper_add_service(hs_version, &pk, port_cfgs, max_streams, max_streams_close_circuit, + pow_defenses_enabled, + pow_queue_rate, + pow_queue_burst, auth_clients_v3, &service_id); port_cfgs = NULL; /* port_cfgs is now owned by the hs_service code. */ auth_clients_v3 = NULL; /* so is auth_clients_v3 */ diff -Nru tor-0.4.8.16/src/feature/control/control_cmd.h tor-0.4.9.6/src/feature/control/control_cmd.h --- tor-0.4.8.16/src/feature/control/control_cmd.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/control/control_cmd.h 2026-03-25 14:30:34.000000000 +0000 @@ -98,6 +98,9 @@ add_onion_secret_key_t *pk, smartlist_t *port_cfgs, int max_streams, int max_streams_close_circuit, + int pow_defenses_enabled, + uint32_t pow_queue_rate, + uint32_t pow_queue_burst, smartlist_t *auth_clients_v3, char **address_out); STATIC control_cmd_args_t *control_cmd_parse_args( diff -Nru tor-0.4.8.16/src/feature/control/control_events.c tor-0.4.9.6/src/feature/control/control_events.c --- tor-0.4.8.16/src/feature/control/control_events.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/control/control_events.c 2026-03-25 14:30:34.000000000 +0000 @@ -1,5 +1,5 @@ /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2021, The Tor Project, Inc. */ + * Copyright (c) 2007-2024, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -1295,6 +1295,21 @@ uint32_t n_written; } cached_bw_events[N_BW_EVENTS_TO_CACHE]; +void +stats_init(void) +{ + stats_prev_n_read = get_bytes_read(); + stats_prev_n_written = get_bytes_written(); +} + +void +stats_clear(void) +{ + memset(cached_bw_events, 0, sizeof cached_bw_events); + stats_prev_n_read = stats_prev_n_written = 0; + n_measurements = next_measurement_idx = 0; +} + /** A second or more has elapsed: tell any interested control * connections how much bandwidth we used. */ int diff -Nru tor-0.4.8.16/src/feature/control/control_events.h tor-0.4.9.6/src/feature/control/control_events.h --- tor-0.4.8.16/src/feature/control/control_events.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/control/control_events.h 2026-03-25 14:30:34.000000000 +0000 @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2021, The Tor Project, Inc. */ + * Copyright (c) 2007-2024, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -226,6 +226,9 @@ int control_event_enter_controller_wait(void); +void stats_init(void); +void stats_clear(void); + void control_events_free_all(void); #ifdef CONTROL_MODULE_PRIVATE diff -Nru tor-0.4.8.16/src/feature/control/control_fmt.c tor-0.4.9.6/src/feature/control/control_fmt.c --- tor-0.4.8.16/src/feature/control/control_fmt.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/control/control_fmt.c 2026-03-25 14:30:34.000000000 +0000 @@ -163,17 +163,25 @@ /* Add conflux id and RTT info, for accurate circuit display. The RTT is * provided to indicate the primary (preferred) circuit of a set - * (which will have the lowest current RTT). */ - if (CIRCUIT_IS_CONFLUX(TO_CIRCUIT(circ))) { + * (which will have the lowest current RTT). + * + * NOTE: Because control port events can happen at arbitrary points, we + * must specifically check exactly what we need from the conflux object. + * We cannot use CIRCUIT_IS_CONFLUX() because this event may have been + * emitted while a set was under partial construction or teardown. */ + if (TO_CIRCUIT(circ)->conflux || TO_CIRCUIT(circ)->conflux_pending_nonce) { const uint8_t *nonce = conflux_get_nonce(TO_CIRCUIT(circ)); tor_assert(nonce); - /* The conflux nonce is sensitive data. Only output half of it. */ + /* The conflux nonce is an ephemeral cryptographic secret that if known in + * full, enables confirmation or data injection on a set by adding new legs + * at an exit from elsewhere. Only output half of it. */ smartlist_add_asprintf(descparts, "CONFLUX_ID=%s", hex_str((const char *)nonce, DIGEST256_LEN/2)); - /* If we have a conflux object, the circ is linked and has an RTT */ - if (TO_CIRCUIT(circ)->conflux) { + /* If we have a conflux object that is fully linked, the circ has an RTT */ + if (TO_CIRCUIT(circ)->conflux && + TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED) { uint64_t circ_rtt = conflux_get_circ_rtt(TO_CIRCUIT(circ)); if (circ_rtt) { smartlist_add_asprintf(descparts, "CONFLUX_RTT=%" PRIu64, circ_rtt); diff -Nru tor-0.4.8.16/src/feature/control/control_getinfo.c tor-0.4.9.6/src/feature/control/control_getinfo.c --- tor-0.4.8.16/src/feature/control/control_getinfo.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/control/control_getinfo.c 2026-03-25 14:30:34.000000000 +0000 @@ -1257,14 +1257,12 @@ router_all_orports_seem_reachable(options) ? "1" : "0"); } else if (!strcmp(question, "status/reachability-succeeded/dir")) { - *answer = tor_strdup( - router_dirport_seems_reachable(options) ? - "1" : "0"); + *answer = tor_strdup("1"); /* obsolete since tor#2667) */ } else if (!strcmp(question, "status/reachability-succeeded")) { tor_asprintf( answer, "OR=%d DIR=%d", router_all_orports_seem_reachable(options) ? 1 : 0, - router_dirport_seems_reachable(options) ? 1 : 0); + 1); } else if (!strcmp(question, "status/bootstrap-phase")) { *answer = control_event_boot_last_msg(); } else if (!strcmpstart(question, "status/version/")) { diff -Nru tor-0.4.8.16/src/feature/control/include.am tor-0.4.9.6/src/feature/control/include.am --- tor-0.4.8.16/src/feature/control/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/control/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -1,11 +1,11 @@ # ADD_C_FILE: INSERT SOURCES HERE. -LIBTOR_APP_A_SOURCES += \ +LIBTOR_APP_A_SOURCES += \ src/feature/control/btrack.c \ src/feature/control/btrack_circuit.c \ src/feature/control/btrack_orconn.c \ - src/feature/control/btrack_orconn_cevent.c \ - src/feature/control/btrack_orconn_maps.c \ + src/feature/control/btrack_orconn_cevent.c\ + src/feature/control/btrack_orconn_maps.c\ src/feature/control/control.c \ src/feature/control/control_auth.c \ src/feature/control/control_bootstrap.c \ diff -Nru tor-0.4.8.16/src/feature/dirauth/dirauth_config.c tor-0.4.9.6/src/feature/dirauth/dirauth_config.c --- tor-0.4.8.16/src/feature/dirauth/dirauth_config.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dirauth/dirauth_config.c 2026-03-25 14:30:34.000000000 +0000 @@ -16,9 +16,12 @@ #include "lib/encoding/confline.h" #include "lib/confmgt/confmgt.h" #include "lib/conf/confdecl.h" +#include "lib/version/torversion.h" /* Required for dirinfo_type_t in or_options_t */ #include "core/or/or.h" +#include "core/or/tor_version_st.h" +#include "core/or/versions.h" #include "app/config/config.h" #include "app/config/resolve_addr.h" @@ -426,6 +429,7 @@ dirauth_options_validate(const void *arg, char **msg) { const dirauth_options_t *options = arg; + tor_version_t minimal_accepted_server_version, recommended_version; if (options->VersioningAuthoritativeDirectory && (!options->RecommendedClientVersions || @@ -439,12 +443,53 @@ REJECT("Guard bandwdith threshold fraction is invalid."); } - char *t; + if (tor_version_parse(options->MinimalAcceptedServerVersion, + &minimal_accepted_server_version) != 0) { + REJECT("Invalid MinimalAcceptedServerVersion"); + } + + tor_assertf(tor_version_parse(get_short_version(), + &recommended_version) == 0, + "We failed to parse our own version"); + if (tor_version_compare(&recommended_version, + &minimal_accepted_server_version) < 0) { + REJECT("MinimalAcceptedServerVersion wants to reject the version " + "this node is running"); + } + + char *recommended_versions; + int found_recommended_rejected_version = 0; /* Call these functions to produce warnings only. */ - t = format_recommended_version_list(options->RecommendedClientVersions, 1); - tor_free(t); - t = format_recommended_version_list(options->RecommendedServerVersions, 1); - tor_free(t); + recommended_versions = format_recommended_version_list( + options->RecommendedClientVersions, 1); + tor_free(recommended_versions); + + recommended_versions = format_recommended_version_list( + options->RecommendedServerVersions, 1); + + smartlist_t *version_sl = smartlist_new(); + smartlist_split_string(version_sl, recommended_versions, ",", + SPLIT_SKIP_SPACE, 0); + SMARTLIST_FOREACH_BEGIN(version_sl, const char *, version) { + if (version[0] != '\0' && tor_version_parse(version, + &recommended_version) != 0) { + COMPLAIN("Found unparseable version in RecommendedServerVersions"); + continue; + } + + if (tor_version_compare(&recommended_version, + &minimal_accepted_server_version) < 0) { + found_recommended_rejected_version = 1; + break; + } + } SMARTLIST_FOREACH_END(version); + + SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version)); + smartlist_free(version_sl); + tor_free(recommended_versions); + if (found_recommended_rejected_version) + REJECT("MinimalAcceptedServerVersion wants to reject a recommended " + "version"); if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) { COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high."); diff -Nru tor-0.4.8.16/src/feature/dirauth/dirauth_options.inc tor-0.4.9.6/src/feature/dirauth/dirauth_options.inc --- tor-0.4.8.16/src/feature/dirauth/dirauth_options.inc 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dirauth/dirauth_options.inc 2026-03-25 14:30:34.000000000 +0000 @@ -76,6 +76,9 @@ /** Which versions of tor should we tell users to run on relays? */ CONF_VAR(RecommendedServerVersions, LINELIST, 0, NULL) +/** Which minimal version of tor do we accept relay descriptors from? */ +CONF_VAR(MinimalAcceptedServerVersion, STRING, 0, "0.4.8.0-alpha-dev") + /** Relays which should be voted Guard regardless of uptime and bandwidth. */ CONF_VAR(AuthDirVoteGuard, ROUTERSET, 0, NULL) diff -Nru tor-0.4.8.16/src/feature/dirauth/dirvote.c tor-0.4.9.6/src/feature/dirauth/dirvote.c --- tor-0.4.8.16/src/feature/dirauth/dirvote.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dirauth/dirvote.c 2026-03-25 14:30:34.000000000 +0000 @@ -115,6 +115,9 @@ char *body; /** The parsed in-progress consensus document. */ networkstatus_t *consensus; + /** Have we reached the critical number of sigs on this consensus, and + * exported it for the consensus transparency module? */ + bool have_exported_for_transparency; } pending_consensus_t; /* DOCDOC dirvote_add_signatures_to_all_pending_consensuses */ @@ -1631,7 +1634,11 @@ n_versioning_servers); client_versions = compute_consensus_versions_list(combined_client_versions, n_versioning_clients); - packages = compute_consensus_package_lines(votes); + + if (consensus_method < MIN_METHOD_TO_OMIT_PACKAGE_FINGERPRINTS) + packages = tor_strdup(""); + else + packages = compute_consensus_package_lines(votes); SMARTLIST_FOREACH(combined_server_versions, char *, cp, tor_free(cp)); SMARTLIST_FOREACH(combined_client_versions, char *, cp, tor_free(cp)); @@ -1776,15 +1783,10 @@ } { - if (consensus_method < MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE) { - max_unmeasured_bw_kb = (int32_t) extract_param_buggy( - params, "maxunmeasuredbw", DEFAULT_MAX_UNMEASURED_BW_KB); - } else { - max_unmeasured_bw_kb = dirvote_get_intermediate_param_value( - param_list, "maxunmeasuredbw", DEFAULT_MAX_UNMEASURED_BW_KB); - if (max_unmeasured_bw_kb < 1) - max_unmeasured_bw_kb = 1; - } + max_unmeasured_bw_kb = dirvote_get_intermediate_param_value( + param_list, "maxunmeasuredbw", DEFAULT_MAX_UNMEASURED_BW_KB); + if (max_unmeasured_bw_kb < 1) + max_unmeasured_bw_kb = 1; } /* Add the actual router entries. */ @@ -2130,7 +2132,7 @@ /* Starting with consensus method 32, we handle the middle-only * flag specially: when it is present, we clear some flags, and * set others. */ - if (is_middle_only && consensus_method >= MIN_METHOD_FOR_MIDDLEONLY) { + if (is_middle_only) { remove_flag(chosen_flags, "Exit"); remove_flag(chosen_flags, "V2Dir"); remove_flag(chosen_flags, "Guard"); @@ -2367,19 +2369,29 @@ { int64_t weight_scale; - if (consensus_method < MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE) { - weight_scale = extract_param_buggy(params, "bwweightscale", - BW_WEIGHT_SCALE); - } else { - weight_scale = dirvote_get_intermediate_param_value( - param_list, "bwweightscale", BW_WEIGHT_SCALE); - if (weight_scale < 1) - weight_scale = 1; - } + weight_scale = dirvote_get_intermediate_param_value( + param_list, "bwweightscale", BW_WEIGHT_SCALE); + if (weight_scale < 1) + weight_scale = 1; added_weights = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D, T, weight_scale); } + /* Write the unsigned proposed consensus text to disk, for dir auth + * debugging purposes, and also to put a sig-less consensus file in + * place for (with luck) later export to the consensus transparency + * module. */ + { + char *unsigned_consensus = smartlist_join_strings(chunks, "", 0, NULL); + char *filename = NULL; + tor_asprintf(&filename, "my-consensus-%s", flavor_name); + char *fpath = get_datadir_fname(filename); + write_str_to_file(fpath, unsigned_consensus, 0); + tor_free(filename); + tor_free(fpath); + tor_free(unsigned_consensus); + } + /* Add a signature. */ { char digest[DIGEST256_LEN]; @@ -2477,53 +2489,6 @@ return result; } -/** Extract the value of a parameter from a string encoding a list of - * parameters, badly. - * - * This is a deliberately buggy implementation, for backward compatibility - * with versions of Tor affected by #19011. Once all authorities have - * upgraded to consensus method 31 or later, then we can throw away this - * function. */ -STATIC int64_t -extract_param_buggy(const char *params, - const char *param_name, - int64_t default_value) -{ - int64_t value = default_value; - const char *param_str = NULL; - - if (params) { - char *prefix1 = NULL, *prefix2=NULL; - tor_asprintf(&prefix1, "%s=", param_name); - tor_asprintf(&prefix2, " %s=", param_name); - if (strcmpstart(params, prefix1) == 0) - param_str = params; - else - param_str = strstr(params, prefix2); - tor_free(prefix1); - tor_free(prefix2); - } - - if (param_str) { - int ok=0; - char *eq = strchr(param_str, '='); - if (eq) { - value = tor_parse_long(eq+1, 10, 1, INT32_MAX, &ok, NULL); - if (!ok) { - log_warn(LD_DIR, "Bad element '%s' in %s", - escaped(param_str), param_name); - value = default_value; - } - } else { - log_warn(LD_DIR, "Bad element '%s' in %s", - escaped(param_str), param_name); - value = default_value; - } - } - - return value; -} - /** Given a list of networkstatus_t for each vote, return a newly allocated * string containing the "package" lines for the vote. */ STATIC char * @@ -3539,16 +3504,6 @@ pending[flav].consensus = consensus; n_generated++; - /* Write it out to disk too, for dir auth debugging purposes */ - { - char *filename; - tor_asprintf(&filename, "my-consensus-%s", flavor_name); - char *fpath = get_datadir_fname(filename); - write_str_to_file(fpath, consensus_body, 0); - tor_free(filename); - tor_free(fpath); - } - consensus_body = NULL; consensus = NULL; } @@ -3614,9 +3569,36 @@ return -1; } -/** Helper: we just got the detached_signatures_body sent to us as - * signatures on the currently pending consensus. Add them to pc - * as appropriate. Return the number of signatures added. (?) */ +/** We just got enough sigs on the pending flavor_name-flavor + * consensus that it is time to export it to the consensus transparency + * module. We do this by writing a "consensus-transparency-%s" file which + * the module will detect and act on. + * + * The file needs to be just the bare consensus, with no signatures, so we + * are registering a hash that everybody can agree on. */ +static void +export_consensus_for_transparency(const char *flavor_name) +{ + char *filename = NULL; + tor_asprintf(&filename, "my-consensus-%s", flavor_name); + char *fpath_from = get_datadir_fname(filename); + tor_free(filename); + tor_asprintf(&filename, "consensus-transparency-%s", flavor_name); + char *fpath_to = get_datadir_fname(filename); + tor_free(filename); + + replace_file(fpath_from, fpath_to); + + log_notice(LD_DIR, "Exported consensus transparency file %s.", + fpath_to); + + tor_free(fpath_from); + tor_free(fpath_to); +} + +/** Helper: we just received sigs as + * signatures on the currently pending consensus. Add them to pc + * as appropriate. Return the number of signatures added, or -1 if error. */ static int dirvote_add_signatures_to_pending_consensus( pending_consensus_t *pc, @@ -3680,6 +3662,16 @@ } *msg_out = "Signatures added"; tor_free(new_signatures); + + /* Check if we now have enough sigs that we are confident this + * will be our consensus. */ + if (!pc->have_exported_for_transparency && + networkstatus_check_consensus_signature(pc->consensus, -1) >= 0) { + /* Yes! Send it to the consensus transparency module. */ + export_consensus_for_transparency(flavor_name); + pc->have_exported_for_transparency = 1; + } + } else if (r == 0) { *msg_out = "Signatures ignored"; } else { @@ -3919,13 +3911,18 @@ STATIC microdesc_t * dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method) { + (void) consensus_method; // Currently unneeded... microdesc_t *result = NULL; char *key = NULL, *summary = NULL, *family = NULL; size_t keylen; smartlist_t *chunks = smartlist_new(); char *output = NULL; - crypto_pk_t *rsa_pubkey = router_get_rsa_onion_pkey(ri->onion_pkey, - ri->onion_pkey_len); + crypto_pk_t *rsa_pubkey = router_get_rsa_onion_pkey(ri->tap_onion_pkey, + ri->tap_onion_pkey_len); + if (!rsa_pubkey) { + /* We do not yet support creating MDs for relays without TAP onion keys. */ + goto done; + } if (crypto_pk_write_public_key_to_string(rsa_pubkey, &key, &keylen)<0) goto done; @@ -3937,20 +3934,22 @@ if (ri->onion_curve25519_pkey) { char kbuf[CURVE25519_BASE64_PADDED_LEN + 1]; - bool add_padding = (consensus_method < MIN_METHOD_FOR_UNPADDED_NTOR_KEY); - curve25519_public_to_base64(kbuf, ri->onion_curve25519_pkey, add_padding); + curve25519_public_to_base64(kbuf, ri->onion_curve25519_pkey, false); smartlist_add_asprintf(chunks, "ntor-onion-key %s\n", kbuf); } if (family) { - if (consensus_method < MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS) { - smartlist_add_asprintf(chunks, "family %s\n", family); - } else { - const uint8_t *id = (const uint8_t *)ri->cache_info.identity_digest; - char *canonical_family = nodefamily_canonicalize(family, id, 0); - smartlist_add_asprintf(chunks, "family %s\n", canonical_family); - tor_free(canonical_family); - } + const uint8_t *id = (const uint8_t *)ri->cache_info.identity_digest; + char *canonical_family = nodefamily_canonicalize(family, id, 0); + smartlist_add_asprintf(chunks, "family %s\n", canonical_family); + tor_free(canonical_family); + } + + if (consensus_method >= MIN_METHOD_FOR_FAMILY_IDS && + ri->family_ids && smartlist_len(ri->family_ids)) { + char *family_ids = smartlist_join_strings(ri->family_ids, " ", 0, NULL); + smartlist_add_asprintf(chunks, "family-ids %s\n", family_ids); + tor_free(family_ids); } if (summary && strcmp(summary, "reject 1-65535")) @@ -4048,10 +4047,8 @@ int high; } microdesc_consensus_methods[] = { {MIN_SUPPORTED_CONSENSUS_METHOD, - MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS - 1}, - {MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS, - MIN_METHOD_FOR_UNPADDED_NTOR_KEY - 1}, - {MIN_METHOD_FOR_UNPADDED_NTOR_KEY, + MIN_METHOD_FOR_FAMILY_IDS - 1}, + {MIN_METHOD_FOR_FAMILY_IDS, MAX_SUPPORTED_CONSENSUS_METHOD}, {-1, -1} }; diff -Nru tor-0.4.8.16/src/feature/dirauth/dirvote.h tor-0.4.9.6/src/feature/dirauth/dirvote.h --- tor-0.4.8.16/src/feature/dirauth/dirvote.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dirauth/dirvote.h 2026-03-25 14:30:34.000000000 +0000 @@ -50,35 +50,28 @@ ((MIN_VOTE_SECONDS_TESTING)+(MIN_DIST_SECONDS_TESTING)+1) /** The lowest consensus method that we currently support. */ -#define MIN_SUPPORTED_CONSENSUS_METHOD 28 +#define MIN_SUPPORTED_CONSENSUS_METHOD 32 /** The highest consensus method that we currently support. */ -#define MAX_SUPPORTED_CONSENSUS_METHOD 33 +#define MAX_SUPPORTED_CONSENSUS_METHOD 35 /** - * Lowest consensus method where microdescriptor lines are put in canonical - * form for improved compressibility and ease of storage. See proposal 298. - **/ -#define MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS 29 - -/** Lowest consensus method where an unpadded base64 onion-key-ntor is allowed - * See #7869 */ -#define MIN_METHOD_FOR_UNPADDED_NTOR_KEY 30 - -/** Lowest consensus method for which we use the correct algorithm for - * extracting the bwweightscale= and maxunmeasuredbw= parameters. See #19011. + * Lowest consensus method for which we suppress the published time in + * microdescriptor consensuses. */ -#define MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE 31 +#define MIN_METHOD_TO_SUPPRESS_MD_PUBLISHED 33 -/** Lowest consensus method for which we handle the MiddleOnly flag specially. - */ -#define MIN_METHOD_FOR_MIDDLEONLY 32 +/** + * Lowest (supported) consensus method for which we do not include + * any "package" lines. + **/ +#define MIN_METHOD_TO_OMIT_PACKAGE_FINGERPRINTS 34 /** - * Lowest consensus method for which we suppress the published time in - * microdescriptor consensuses. + * Lowest supported consensus method for which we include `family-ids` + * in microdescs. */ -#define MIN_METHOD_TO_SUPPRESS_MD_PUBLISHED 33 +#define MIN_METHOD_FOR_FAMILY_IDS 35 /** Default bandwidth to clip unmeasured bandwidths to using method >= * MIN_METHOD_TO_CLIP_UNMEASURED_BW. (This is not a consensus method; do not @@ -274,9 +267,6 @@ char *networkstatus_get_detached_signatures(smartlist_t *consensuses); STATIC microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method); -STATIC int64_t extract_param_buggy(const char *params, - const char *param_name, - int64_t default_value); #endif /* defined(DIRVOTE_PRIVATE) */ diff -Nru tor-0.4.8.16/src/feature/dirauth/process_descs.c tor-0.4.9.6/src/feature/dirauth/process_descs.c --- tor-0.4.8.16/src/feature/dirauth/process_descs.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dirauth/process_descs.c 2026-03-25 14:30:34.000000000 +0000 @@ -410,8 +410,8 @@ static const char please_upgrade_string[] = "Tor version is insecure or unsupported. Please upgrade!"; - /* Anything before 0.4.8.0 is unsupported. Reject them. */ - if (!tor_version_as_new_as(platform,"0.4.8.0-alpha-dev")) { + if (!tor_version_as_new_as(platform, + dirauth_get_options()->MinimalAcceptedServerVersion)) { if (msg) { *msg = please_upgrade_string; } @@ -771,6 +771,16 @@ log_info(LD_DIR, "Assessing new descriptor: %s: %s", ri->nickname, ri->platform); + /* For now, TAP keys are still required. */ + if (! ri->tap_onion_pkey) { + log_info(LD_DIRSERV, "Rejecting descriptor from %s (source: %s); " + "it has no TAP key.", + router_describe(ri), source); + *msg = "Missing TAP key in descriptor."; + r = ROUTER_AUTHDIR_REJECTS; + goto fail; + } + /* Check whether this descriptor is semantically identical to the last one * from this server. (We do this here and not in router_add_to_routerlist * because we want to be able to accept the newest router descriptor that diff -Nru tor-0.4.8.16/src/feature/dirauth/voteflags.c tor-0.4.9.6/src/feature/dirauth/voteflags.c --- tor-0.4.8.16/src/feature/dirauth/voteflags.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dirauth/voteflags.c 2026-03-25 14:30:34.000000000 +0000 @@ -112,8 +112,7 @@ } /** Return 1 if ri's descriptor is "active" -- running, valid, - * not hibernating, having observed bw greater 0, and not too old. Else - * return 0. + * not hibernating, and not too old. Else return 0. */ static int router_is_active(const routerinfo_t *ri, const node_t *node, time_t now) @@ -125,20 +124,6 @@ if (!node->is_running || !node->is_valid || ri->is_hibernating) { return 0; } - /* Only require bandwidth capacity in non-test networks, or - * if TestingTorNetwork, and TestingMinExitFlagThreshold is non-zero */ - if (!ri->bandwidthcapacity) { - if (get_options()->TestingTorNetwork) { - if (dirauth_get_options()->TestingMinExitFlagThreshold > 0) { - /* If we're in a TestingTorNetwork, and TestingMinExitFlagThreshold is, - * then require bandwidthcapacity */ - return 0; - } - } else { - /* If we're not in a TestingTorNetwork, then require bandwidthcapacity */ - return 0; - } - } return 1; } diff -Nru tor-0.4.8.16/src/feature/dircache/dircache.c tor-0.4.9.6/src/feature/dircache/dircache.c --- tor-0.4.8.16/src/feature/dircache/dircache.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dircache/dircache.c 2026-03-25 14:30:34.000000000 +0000 @@ -968,12 +968,12 @@ goto done; } + /* Success: we are going to try serving it. */ + geoip_note_ns_response(GEOIP_SERVED); + conn->should_count_geoip_when_finished = 1; + tor_addr_t addr; if (tor_addr_parse(&addr, (TO_CONN(conn))->address) >= 0) { - geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, - &addr, NULL, - time(NULL)); - geoip_note_ns_response(GEOIP_SUCCESS); /* Note that a request for a network status has started, so that we * can measure the download time later on. */ if (conn->dirreq_id) diff -Nru tor-0.4.8.16/src/feature/dircache/dirserv.c tor-0.4.9.6/src/feature/dircache/dirserv.c --- tor-0.4.8.16/src/feature/dircache/dirserv.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dircache/dirserv.c 2026-03-25 14:30:34.000000000 +0000 @@ -15,6 +15,7 @@ #include "feature/nodelist/routerlist.h" #include "feature/relay/router.h" #include "feature/relay/routermode.h" +#include "feature/stats/geoip_stats.h" #include "feature/stats/predict_ports.h" #include "feature/dircache/cached_dir_st.h" @@ -778,6 +779,22 @@ tor_compress_free(conn->compress_state); conn->compress_state = NULL; } + + /* only count networkstatus serves as successful when the spool runs dry */ + if (conn->should_count_geoip_when_finished) { + tor_addr_t addr; + /* but as a special case, check if conn is on a circuit that used a + * version-0 sendme (bugs 41191 and 41192), because we don't want to + * count clients that should exit after they receive our consensus. */ + if (!connection_dir_used_obsolete_sendme(conn) && + tor_addr_parse(&addr, (TO_CONN(conn))->address) >= 0) { + geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, + &addr, NULL, + time(NULL)); + } + geoip_note_ns_response(GEOIP_SUCCESS); + conn->should_count_geoip_when_finished = 0; + } return 0; } diff -Nru tor-0.4.8.16/src/feature/dirclient/dirclient.c tor-0.4.9.6/src/feature/dirclient/dirclient.c --- tor-0.4.8.16/src/feature/dirclient/dirclient.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dirclient/dirclient.c 2026-03-25 14:30:34.000000000 +0000 @@ -688,7 +688,6 @@ /* We rejected all addresses in the relay's status. This means we can't * connect to it. */ if (!have_or && !have_dir) { - static int logged_backtrace = 0; char *ipv6_str = tor_addr_to_str_dup(&status->ipv6_addr); log_info(LD_BUG, "Rejected all OR and Dir addresses from %s when " "launching an outgoing directory connection to: IPv4 %s OR %d " @@ -697,10 +696,7 @@ status->ipv4_dirport, ipv6_str, status->ipv6_orport, status->ipv4_dirport); tor_free(ipv6_str); - if (!logged_backtrace) { - log_backtrace(LOG_INFO, LD_BUG, "Addresses came from"); - logged_backtrace = 1; - } + log_backtrace_once(LOG_INFO, LD_BUG, "Addresses came from"); return -1; } @@ -1325,15 +1321,11 @@ /* Make sure that the destination addr and port we picked is viable. */ if (!port || tor_addr_is_null(&addr)) { - static int logged_backtrace = 0; log_warn(LD_DIR, "Cannot make an outgoing %sconnection without a remote %sPort.", use_begindir ? "begindir " : "", use_begindir ? "OR" : "Dir"); - if (!logged_backtrace) { - log_backtrace(LOG_INFO, LD_BUG, "Address came from"); - logged_backtrace = 1; - } + log_backtrace_once(LOG_INFO, LD_BUG, "Address came from"); return; } diff -Nru tor-0.4.8.16/src/feature/dircommon/dir_connection_st.h tor-0.4.9.6/src/feature/dircommon/dir_connection_st.h --- tor-0.4.8.16/src/feature/dircommon/dir_connection_st.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dircommon/dir_connection_st.h 2026-03-25 14:30:34.000000000 +0000 @@ -61,6 +61,10 @@ * needs this for the incoming side, so it's moved here. */ uint64_t dirreq_id; + /** 0 normally, 1 if we're serving a consensus and we're delaying counting + * geoip until we've served the final bytes. */ + bool should_count_geoip_when_finished; + #ifdef MEASUREMENTS_21206 /** Number of RELAY_DATA cells received. */ uint32_t data_cells_received; diff -Nru tor-0.4.8.16/src/feature/dircommon/directory.c tor-0.4.9.6/src/feature/dircommon/directory.c --- tor-0.4.8.16/src/feature/dircommon/directory.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dircommon/directory.c 2026-03-25 14:30:34.000000000 +0000 @@ -264,6 +264,38 @@ return !channel_is_client(CONST_TO_OR_CIRCUIT(circ)->p_chan); } +/** Did conn ever send us a version 0 sendme cell and we allowed + * it? Used to decide whether to count consensus fetches from it in our + * geoip stats. + * + * Note that this function might have false negatives in some cases, i.e. + * it could tell us that the conn never sent a v0 sendme when actually it + * did but its linked edge connection or OR connection got broken before + * we called this function. For our geoip stats these false negatives + * would mean overcounting users by including some of the v0-using + * clients. + * + * We think these false positives should be unlikely or maybe even + * impossible when called from connection_dirserv_flushed_some(), but + * be careful calling it from elsewhere. + * */ +bool +connection_dir_used_obsolete_sendme(const dir_connection_t *conn) +{ + const edge_connection_t *edge_conn = NULL; + const circuit_t *circ = NULL; + bool used_obsolete_sendme = 0; + const connection_t *linked_conn = TO_CONN(conn)->linked_conn; + if (linked_conn) + edge_conn = CONST_TO_EDGE_CONN(linked_conn); + if (edge_conn) + circ = edge_conn->on_circuit; + if (circ && CIRCUIT_IS_ORCIRC(circ)) + used_obsolete_sendme = CONST_TO_OR_CIRCUIT(circ)->used_obsolete_sendme; + + return used_obsolete_sendme; +} + /** Parse an HTTP request line at the start of a headers string. On failure, * return -1. On success, set *command_out to a copy of the HTTP * command ("get", "post", etc), set *url_out to a copy of the URL, and @@ -328,7 +360,7 @@ const char *cp = headers; while (cp) { if (!strcasecmpstart(cp, which)) { - char *eos; + const char *eos; cp += strlen(which); if ((eos = strchr(cp,'\r'))) return tor_strndup(cp, eos-cp); diff -Nru tor-0.4.8.16/src/feature/dircommon/directory.h tor-0.4.9.6/src/feature/dircommon/directory.h --- tor-0.4.8.16/src/feature/dircommon/directory.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dircommon/directory.h 2026-03-25 14:30:34.000000000 +0000 @@ -95,6 +95,7 @@ int connection_dir_is_encrypted(const dir_connection_t *conn); bool connection_dir_is_anonymous(const dir_connection_t *conn); +bool connection_dir_used_obsolete_sendme(const dir_connection_t *conn); int connection_dir_reached_eof(dir_connection_t *conn); int connection_dir_process_inbuf(dir_connection_t *conn); int connection_dir_finished_flushing(dir_connection_t *conn); diff -Nru tor-0.4.8.16/src/feature/dircommon/include.am tor-0.4.9.6/src/feature/dircommon/include.am --- tor-0.4.8.16/src/feature/dircommon/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dircommon/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -1,6 +1,6 @@ # ADD_C_FILE: INSERT SOURCES HERE. -LIBTOR_APP_A_SOURCES += \ +LIBTOR_APP_A_SOURCES += \ src/feature/dircommon/consdiff.c \ src/feature/dircommon/directory.c \ src/feature/dircommon/fp_pair.c diff -Nru tor-0.4.8.16/src/feature/dirparse/microdesc_parse.c tor-0.4.9.6/src/feature/dirparse/microdesc_parse.c --- tor-0.4.8.16/src/feature/dirparse/microdesc_parse.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dirparse/microdesc_parse.c 2026-03-25 14:30:34.000000000 +0000 @@ -30,11 +30,12 @@ /** List of tokens recognized in microdescriptors */ // clang-format off static token_rule_t microdesc_token_table[] = { - T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024), + T1_START("onion-key", K_ONION_KEY, NO_ARGS, OPT_KEY_1024), T1("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ), T0N("id", K_ID, GE(2), NO_OBJ ), T0N("a", K_A, GE(1), NO_OBJ ), T01("family", K_FAMILY, CONCAT_ARGS, NO_OBJ ), + T01("family-ids", K_FAMILY_IDS, CONCAT_ARGS, NO_OBJ ), T01("p", K_P, CONCAT_ARGS, NO_OBJ ), T01("p6", K_P6, CONCAT_ARGS, NO_OBJ ), A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ ), @@ -200,14 +201,11 @@ } tok = find_by_keyword(tokens, K_ONION_KEY); - if (!crypto_pk_public_exponent_ok(tok->key)) { + if (tok && tok->key && !crypto_pk_public_exponent_ok(tok->key)) { log_warn(LD_DIR, "Relay's onion key had invalid exponent."); goto err; } - md->onion_pkey = tor_memdup(tok->object_body, tok->object_size); - md->onion_pkey_len = tok->object_size; - crypto_pk_free(tok->key); if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) { curve25519_public_key_t k; @@ -255,6 +253,16 @@ NULL, NF_WARN_MALFORMED); } + if ((tok = find_opt_by_keyword(tokens, K_FAMILY_IDS))) { + smartlist_t *ids = smartlist_new(); + smartlist_split_string(ids, tok->args[0], " ", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + if (smartlist_len(ids) > 0) { + md->family_ids = ids; + } else { + smartlist_free(ids); + } + } if ((tok = find_opt_by_keyword(tokens, K_P))) { md->exit_policy = parse_short_policy(tok->args[0]); diff -Nru tor-0.4.8.16/src/feature/dirparse/parsecommon.c tor-0.4.9.6/src/feature/dirparse/parsecommon.c --- tor-0.4.8.16/src/feature/dirparse/parsecommon.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dirparse/parsecommon.c 2026-03-25 14:30:34.000000000 +0000 @@ -215,6 +215,16 @@ RET_ERR(ebuf); } break; + case OPT_KEY_1024: + /* If there is anything, it must be a 1024-bit RSA key. */ + if (tok->object_body && !tok->key) { + tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd); + RET_ERR(ebuf); + } + if (!tok->key) { + break; + } + FALLTHROUGH; case NEED_KEY_1024: /* There must be a 1024-bit public key. */ if (tok->key && crypto_pk_num_bits(tok->key) != PK_BYTES*8) { tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits", @@ -395,7 +405,8 @@ } if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */ - if (o_syn != NEED_KEY && o_syn != NEED_KEY_1024 && o_syn != OBJ_OK) { + if (o_syn != OPT_KEY_1024 && o_syn != NEED_KEY && + o_syn != NEED_KEY_1024 && o_syn != OBJ_OK) { RET_ERR("Unexpected public key."); } tok->key = crypto_pk_asn1_decode(tok->object_body, tok->object_size); diff -Nru tor-0.4.8.16/src/feature/dirparse/parsecommon.h tor-0.4.9.6/src/feature/dirparse/parsecommon.h --- tor-0.4.8.16/src/feature/dirparse/parsecommon.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dirparse/parsecommon.h 2026-03-25 14:30:34.000000000 +0000 @@ -45,6 +45,8 @@ K_UPTIME, K_DIR_SIGNING_KEY, K_FAMILY, + K_FAMILY_CERT, + K_FAMILY_IDS, K_FINGERPRINT, K_HIBERNATING, K_READ_HISTORY, @@ -220,6 +222,7 @@ typedef enum { NO_OBJ, /**< No object, ever. */ NEED_OBJ, /**< Object is required. */ + OPT_KEY_1024, /**< If object is present, it must be a 1024 bit public key */ NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */ NEED_KEY, /**< Object is required, and must be a public key. */ OBJ_OK, /**< Object is optional. */ diff -Nru tor-0.4.8.16/src/feature/dirparse/routerparse.c tor-0.4.9.6/src/feature/dirparse/routerparse.c --- tor-0.4.8.16/src/feature/dirparse/routerparse.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dirparse/routerparse.c 2026-03-25 14:30:34.000000000 +0000 @@ -51,6 +51,7 @@ **/ #define ROUTERDESC_TOKEN_TABLE_PRIVATE +#define ROUTERPARSE_PRIVATE #include "core/or/or.h" #include "app/config/config.h" @@ -90,7 +91,7 @@ T1_START( "router", K_ROUTER, GE(5), NO_OBJ ), T01("ipv6-policy", K_IPV6_POLICY, CONCAT_ARGS, NO_OBJ), T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ), - T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ), + T01("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ), T1("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ), T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ), T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ), @@ -107,13 +108,14 @@ T1("identity-ed25519", K_IDENTITY_ED25519, NO_ARGS, NEED_OBJ ), T1("master-key-ed25519", K_MASTER_KEY_ED25519, GE(1), NO_OBJ ), T1("router-sig-ed25519", K_ROUTER_SIG_ED25519, GE(1), NO_OBJ ), - T1("onion-key-crosscert", K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ), + T01("onion-key-crosscert", K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ), T1("ntor-onion-key-crosscert", K_NTOR_ONION_KEY_CROSSCERT, EQ(1), NEED_OBJ ), T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS, NO_ARGS, NO_OBJ ), T01("family", K_FAMILY, ARGS, NO_OBJ ), + T0N("family-cert", K_FAMILY_CERT, ARGS, NEED_OBJ ), T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ), T0N("or-address", K_OR_ADDRESS, GE(1), NO_OBJ ), @@ -172,6 +174,10 @@ /* static function prototypes */ static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok); static smartlist_t *find_all_exitpolicy(smartlist_t *s); +static int check_family_certs(const smartlist_t *family_cert_tokens, + const ed25519_public_key_t *identity_key, + smartlist_t **family_ids_out, + time_t *family_expiration_out); /** Set digest to the SHA-1 digest of the hash of the first router in * s. Return 0 on success, -1 on failure. @@ -595,15 +601,17 @@ if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0) goto err; - tok = find_by_keyword(tokens, K_ONION_KEY); - if (!crypto_pk_public_exponent_ok(tok->key)) { - log_warn(LD_DIR, - "Relay's onion key had invalid exponent."); - goto err; + tok = find_opt_by_keyword(tokens, K_ONION_KEY); + if (tok) { + if (!crypto_pk_public_exponent_ok(tok->key)) { + log_warn(LD_DIR, + "Relay's onion key had invalid exponent."); + goto err; + } + router->tap_onion_pkey = tor_memdup(tok->object_body, tok->object_size); + router->tap_onion_pkey_len = tok->object_size; + crypto_pk_free(tok->key); } - router->onion_pkey = tor_memdup(tok->object_body, tok->object_size); - router->onion_pkey_len = tok->object_size; - crypto_pk_free(tok->key); if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) { curve25519_public_key_t k; @@ -627,26 +635,68 @@ { directory_token_t *ed_sig_tok, *ed_cert_tok, *cc_tap_tok, *cc_ntor_tok, *master_key_tok; - ed_sig_tok = find_opt_by_keyword(tokens, K_ROUTER_SIG_ED25519); - ed_cert_tok = find_opt_by_keyword(tokens, K_IDENTITY_ED25519); - master_key_tok = find_opt_by_keyword(tokens, K_MASTER_KEY_ED25519); + ed_sig_tok = find_by_keyword(tokens, K_ROUTER_SIG_ED25519); + ed_cert_tok = find_by_keyword(tokens, K_IDENTITY_ED25519); + master_key_tok = find_by_keyword(tokens, K_MASTER_KEY_ED25519); + cc_ntor_tok = find_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT); + /* This, and only this, is optional. */ cc_tap_tok = find_opt_by_keyword(tokens, K_ONION_KEY_CROSSCERT); - cc_ntor_tok = find_opt_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT); - int n_ed_toks = !!ed_sig_tok + !!ed_cert_tok + - !!cc_tap_tok + !!cc_ntor_tok; - if ((n_ed_toks != 0 && n_ed_toks != 4) || - (n_ed_toks == 4 && !router->onion_curve25519_pkey)) { - log_warn(LD_DIR, "Router descriptor with only partial ed25519/" - "cross-certification support"); + + if (bool_neq(cc_tap_tok==NULL, router->tap_onion_pkey==NULL)) { + log_warn(LD_DIR, "Router descriptor had only one of (onion-key, " + "onion-key-crosscert)."); goto err; } - if (master_key_tok && !ed_sig_tok) { - log_warn(LD_DIR, "Router descriptor has ed25519 master key but no " - "certificate"); + + IF_BUG_ONCE(! (ed_sig_tok && ed_cert_tok&& cc_ntor_tok &&master_key_tok)) { goto err; } - if (ed_sig_tok) { - tor_assert(ed_cert_tok && cc_tap_tok && cc_ntor_tok); + + tor_cert_t *cert; + { + /* Parse the identity certificate */ + cert = tor_cert_parse( + (const uint8_t*)ed_cert_tok->object_body, + ed_cert_tok->object_size); + if (! cert) { + log_warn(LD_DIR, "Couldn't parse ed25519 cert"); + goto err; + } + /* makes sure it gets freed. */ + router->cache_info.signing_key_cert = cert; + + if (cert->cert_type != CERT_TYPE_ID_SIGNING || + ! cert->signing_key_included) { + log_warn(LD_DIR, "Invalid form for ed25519 cert"); + goto err; + } + } + + if (cc_tap_tok) { + rsa_pubkey = router_get_rsa_onion_pkey(router->tap_onion_pkey, + router->tap_onion_pkey_len); + if (rsa_pubkey == NULL) { + log_warn(LD_DIR, "No pubkey for TAP cross-verification."); + goto err; + } + if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) { + log_warn(LD_DIR, "Wrong object type on onion-key-crosscert " + "in descriptor"); + goto err; + } + if (check_tap_onion_key_crosscert( + (const uint8_t*)cc_tap_tok->object_body, + (int)cc_tap_tok->object_size, + rsa_pubkey, + &cert->signing_key, + (const uint8_t*)router->cache_info.identity_digest)<0) { + log_warn(LD_DIR, "Incorrect TAP cross-verification"); + goto err; + } + } + + { + tor_assert(ed_sig_tok && ed_cert_tok && cc_ntor_tok); const int ed_cert_token_pos = smartlist_pos(tokens, ed_cert_tok); if (ed_cert_token_pos == -1 || router_token_pos == -1 || (ed_cert_token_pos != router_token_pos + 1 && @@ -668,35 +718,14 @@ "in descriptor"); goto err; } - if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) { - log_warn(LD_DIR, "Wrong object type on onion-key-crosscert " - "in descriptor"); - goto err; - } if (strcmp(cc_ntor_tok->args[0], "0") && strcmp(cc_ntor_tok->args[0], "1")) { log_warn(LD_DIR, "Bad sign bit on ntor-onion-key-crosscert"); goto err; } int ntor_cc_sign_bit = !strcmp(cc_ntor_tok->args[0], "1"); - uint8_t d256[DIGEST256_LEN]; const char *signed_start, *signed_end; - tor_cert_t *cert = tor_cert_parse( - (const uint8_t*)ed_cert_tok->object_body, - ed_cert_tok->object_size); - if (! cert) { - log_warn(LD_DIR, "Couldn't parse ed25519 cert"); - goto err; - } - /* makes sure it gets freed. */ - router->cache_info.signing_key_cert = cert; - - if (cert->cert_type != CERT_TYPE_ID_SIGNING || - ! cert->signing_key_included) { - log_warn(LD_DIR, "Invalid form for ed25519 cert"); - goto err; - } if (master_key_tok) { /* This token is optional, but if it's present, it must match @@ -746,6 +775,7 @@ crypto_digest_add_bytes(d, ED_DESC_SIGNATURE_PREFIX, strlen(ED_DESC_SIGNATURE_PREFIX)); crypto_digest_add_bytes(d, signed_start, signed_end-signed_start); + crypto_digest_get_digest(d, (char*)d256, sizeof(d256)); crypto_digest_free(d); @@ -776,18 +806,6 @@ goto err; } - rsa_pubkey = router_get_rsa_onion_pkey(router->onion_pkey, - router->onion_pkey_len); - if (check_tap_onion_key_crosscert( - (const uint8_t*)cc_tap_tok->object_body, - (int)cc_tap_tok->object_size, - rsa_pubkey, - &cert->signing_key, - (const uint8_t*)router->cache_info.identity_digest)<0) { - log_warn(LD_DIR, "Incorrect TAP cross-verification"); - goto err; - } - /* We check this before adding it to the routerlist. */ router->cert_expiration_time = expires; } @@ -882,6 +900,21 @@ } } + { + smartlist_t *family_cert_toks = find_all_by_keyword(tokens, K_FAMILY_CERT); + time_t family_expiration = TIME_MAX; + int r = 0; + if (family_cert_toks) { + r = check_family_certs(family_cert_toks, + &router->cache_info.signing_key_cert->signing_key, + &router->family_ids, + &family_expiration); + smartlist_free(family_cert_toks); + } + if (r<0) + goto err; + } + if (find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO)) router->caches_extra_info = 1; @@ -1238,6 +1271,115 @@ return out; } +/** + * Parse and validate a single `FAMILY_CERT` token's object. + * + * Arguments are as for `check_family_certs()`. + */ +STATIC int +check_one_family_cert(const uint8_t *cert_body, + size_t cert_body_size, + const ed25519_public_key_t *identity_key, + char **family_id_out, + time_t *family_expiration_out) +{ + tor_cert_t *cert = NULL; + int r = -1; + + cert = tor_cert_parse(cert_body, cert_body_size); + + if (! cert) + goto done; + if (cert->cert_type != CERT_TYPE_FAMILY_V_IDENTITY) { + log_warn(LD_DIR, "Wrong cert type in family certificate."); + goto done; + } + if (! cert->signing_key_included) { + log_warn(LD_DIR, "Missing family key in family certificate."); + goto done; + } + if (! ed25519_pubkey_eq(&cert->signed_key, identity_key)) { + log_warn(LD_DIR, "Key mismatch in family certificate."); + goto done; + } + + time_t valid_until = cert->valid_until; + + /* We're using NULL for the key, since the cert has the signing key included. + * We're using 0 for "now", since we're going to extract the expiration + * separately. + */ + if (tor_cert_checksig(cert, NULL, 0) < 0) { + log_warn(LD_DIR, "Invalid signature in family certificate"); + goto done; + } + + /* At this point we know that the cert is valid. + * We extract the expiration time and the signing key. */ + *family_expiration_out = valid_until; + + char buf[ED25519_BASE64_LEN+1]; + ed25519_public_to_base64(buf, &cert->signing_key); + tor_asprintf(family_id_out, "ed25519:%s", buf); + + r = 0; + done: + tor_cert_free(cert); + return r; +} + +/** + * Given a list of `FAMILY_CERT` tokens, and a relay's ed25519 `identity_key`, + * validate the family certificates in all the tokens, and convert them into + * family IDs in a newly allocated `family_ids_out` list. + * Set `family_expiration_out` to the earliest time at which any certificate + * in the list expires. + * Return 0 on success, and -1 on failure. + */ +static int +check_family_certs(const smartlist_t *family_cert_tokens, + const ed25519_public_key_t *identity_key, + smartlist_t **family_ids_out, + time_t *family_expiration_out) +{ + if (BUG(!identity_key) || + BUG(!family_ids_out) || + BUG(!family_expiration_out)) + return -1; + + *family_expiration_out = TIME_MAX; + + if (family_cert_tokens == NULL || smartlist_len(family_cert_tokens) == 0) { + *family_ids_out = NULL; + return 0; + } + + *family_ids_out = smartlist_new(); + SMARTLIST_FOREACH_BEGIN(family_cert_tokens, directory_token_t *, tok) { + if (BUG(tok->object_body == NULL)) + goto err; + + char *this_id = NULL; + time_t this_expiration = TIME_MAX; + if (check_one_family_cert((const uint8_t*)tok->object_body, + tok->object_size, + identity_key, + &this_id, &this_expiration) < 0) + goto err; + smartlist_add(*family_ids_out, this_id); + *family_expiration_out = MIN(*family_expiration_out, this_expiration); + } SMARTLIST_FOREACH_END(tok); + + smartlist_sort_strings(*family_ids_out); + smartlist_uniq_strings(*family_ids_out); + + return 0; + err: + SMARTLIST_FOREACH(*family_ids_out, char *, cp, tor_free(cp)); + smartlist_free(*family_ids_out); + return -1; +} + /** Called on startup; right now we just handle scanning the unparseable * descriptor dumps, but hang anything else we might need to do in the * future here as well. diff -Nru tor-0.4.8.16/src/feature/dirparse/routerparse.h tor-0.4.9.6/src/feature/dirparse/routerparse.h --- tor-0.4.8.16/src/feature/dirparse/routerparse.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/dirparse/routerparse.h 2026-03-25 14:30:34.000000000 +0000 @@ -12,6 +12,8 @@ #ifndef TOR_ROUTERPARSE_H #define TOR_ROUTERPARSE_H +#include "lib/testsupport/testsupport.h" + int router_get_router_hash(const char *s, size_t s_len, char *digest); int router_get_extrainfo_hash(const char *s, size_t s_len, char *digest); @@ -47,4 +49,12 @@ #define ED_DESC_SIGNATURE_PREFIX "Tor router descriptor signature v1" +#ifdef ROUTERPARSE_PRIVATE +STATIC int check_one_family_cert(const uint8_t *cert_body, + size_t cert_body_size, + const struct ed25519_public_key_t *identity_key, + char **family_id_out, + time_t *family_expiration_out); +#endif + #endif /* !defined(TOR_ROUTERPARSE_H) */ diff -Nru tor-0.4.8.16/src/feature/hibernate/hibernate.c tor-0.4.9.6/src/feature/hibernate/hibernate.c --- tor-0.4.8.16/src/feature/hibernate/hibernate.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hibernate/hibernate.c 2026-03-25 14:30:34.000000000 +0000 @@ -930,6 +930,15 @@ } /** + * Return true iff we are currently shutting down. + */ +MOCK_IMPL(int, +we_are_shutting_down,(void)) +{ + return hibernate_state == HIBERNATE_STATE_EXITING; +} + +/** * Return true iff we are currently hibernating -- that is, if we are in * any non-live state. */ diff -Nru tor-0.4.8.16/src/feature/hibernate/hibernate.h tor-0.4.9.6/src/feature/hibernate/hibernate.h --- tor-0.4.8.16/src/feature/hibernate/hibernate.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hibernate/hibernate.h 2026-03-25 14:30:34.000000000 +0000 @@ -24,6 +24,7 @@ void accounting_add_bytes(size_t n_read, size_t n_written, int seconds); int accounting_record_bandwidth_usage(time_t now, or_state_t *state); void hibernate_begin_shutdown(void); +MOCK_DECL(int, we_are_shutting_down, (void)); MOCK_DECL(int, we_are_hibernating, (void)); MOCK_DECL(int, we_are_fully_hibernating,(void)); void consider_hibernation(time_t now); diff -Nru tor-0.4.8.16/src/feature/hibernate/include.am tor-0.4.9.6/src/feature/hibernate/include.am --- tor-0.4.8.16/src/feature/hibernate/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hibernate/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -4,5 +4,5 @@ src/feature/hibernate/hibernate.c # ADD_C_FILE: INSERT HEADERS HERE. -noinst_HEADERS += \ +noinst_HEADERS += \ src/feature/hibernate/hibernate.h diff -Nru tor-0.4.8.16/src/feature/hs/hs_cache.c tor-0.4.9.6/src/feature/hs/hs_cache.c --- tor-0.4.8.16/src/feature/hs/hs_cache.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs/hs_cache.c 2026-03-25 14:30:34.000000000 +0000 @@ -26,6 +26,11 @@ #include "feature/nodelist/networkstatus_st.h" +/** + * Spare room for 1000 descriptors when pruning cache to avoid thrashing + * and memory fragmentation. */ +#define HSCACHE_PRUNE_SPARE_ROOM (1000 * HS_DESC_MAX_LEN) + /* Total counter of the cache size. */ static size_t hs_cache_total_allocation = 0; @@ -148,6 +153,29 @@ tor_assert(desc); + /* Check if we've exceeded the MaxHSDirCacheBytes limit after adding + * this descriptor. If so, prune excess bytes leaving room for more. */ + const size_t max_cache_bytes = hs_cache_get_max_bytes(); + const size_t current_cache_bytes = hs_cache_get_total_allocation(); + if (max_cache_bytes > 0 && current_cache_bytes > max_cache_bytes) { + /* We prune only 1000 descriptors worth of memory here because + * pruning is an expensive O(n^2) option to keep finding lowest + * download count descs. */ + size_t bytes_to_remove = current_cache_bytes/2; + /* Ensure user didn't set a really low max hsdir cache vlue */ + if (HSCACHE_PRUNE_SPARE_ROOM < max_cache_bytes) { + bytes_to_remove = current_cache_bytes - + (max_cache_bytes - HSCACHE_PRUNE_SPARE_ROOM); + } + size_t removed = hs_cache_handle_oom(bytes_to_remove); + static ratelim_t hs_cache_oom_ratelim = RATELIM_INIT(600); + log_fn_ratelim(&hs_cache_oom_ratelim, LOG_NOTICE, LD_REND, + "HSDir cache exceeded limit " + "(%"TOR_PRIuSZ " > %"TOR_PRIuSZ " bytes). " + "Pruned %"TOR_PRIuSZ " bytes during an HS descriptor upload.", + current_cache_bytes, max_cache_bytes, removed); + } + /* Verify if we have an entry in the cache for that key and if yes, check * if we should replace it? */ cache_entry = lookup_v3_desc_as_dir(desc->key); @@ -164,15 +192,21 @@ goto err; } /* We now know that the descriptor we just received is a new one so + * preserve the downloaded counter from the old entry and then * remove the entry we currently have from our cache so we can then * store the new one. */ + desc->n_downloaded = cache_entry->n_downloaded; remove_v3_desc_as_dir(cache_entry); hs_cache_decrement_allocation(cache_get_dir_entry_size(cache_entry)); cache_dir_desc_free(cache_entry); } + /* Store the descriptor we just got. We are sure here that either we * don't have the entry or we have a newer descriptor and the old one - * has been removed from the cache. */ + * has been removed from the cache. We do this *after* pruning + * other descriptors so that this descriptor is not immediately pruned, + * if new. This prevents probing to detect OOM threshholds via its + * absence. */ store_v3_desc_as_dir(desc); /* Update our total cache size with this entry for the OOM. This uses the @@ -1221,6 +1255,14 @@ hs_cache_total_allocation = 0; } +/** Get the configured maximum cache size. */ +uint64_t +hs_cache_get_max_bytes(void) +{ + uint64_t opt = get_options()->MaxHSDirCacheBytes; + return opt != 0 ? opt : get_options()->MaxMemInQueues / 5; +} + /* Return total size of the cache. */ size_t hs_cache_get_total_allocation(void) diff -Nru tor-0.4.8.16/src/feature/hs/hs_cache.h tor-0.4.9.6/src/feature/hs/hs_cache.h --- tor-0.4.8.16/src/feature/hs/hs_cache.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs/hs_cache.h 2026-03-25 14:30:34.000000000 +0000 @@ -122,6 +122,7 @@ bool hs_cache_client_new_auth_parse(const ed25519_public_key_t *service_pk); +uint64_t hs_cache_get_max_bytes(void); size_t hs_cache_get_total_allocation(void); void hs_cache_decrement_allocation(size_t n); void hs_cache_increment_allocation(size_t n); diff -Nru tor-0.4.8.16/src/feature/hs/hs_cell.c tor-0.4.9.6/src/feature/hs/hs_cell.c --- tor-0.4.8.16/src/feature/hs/hs_cell.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs/hs_cell.c 2026-03-25 14:30:34.000000000 +0000 @@ -41,7 +41,7 @@ { size_t offset = 0; size_t mac_msg_len; - uint8_t mac_msg[RELAY_PAYLOAD_SIZE] = {0}; + uint8_t mac_msg[RELAY_PAYLOAD_SIZE_MAX] = {0}; tor_assert(encoded_cell); tor_assert(encrypted); @@ -299,8 +299,8 @@ size_t offset = 0; ssize_t encrypted_len; ssize_t encoded_cell_len, encoded_enc_cell_len; - uint8_t encoded_cell[RELAY_PAYLOAD_SIZE] = {0}; - uint8_t encoded_enc_cell[RELAY_PAYLOAD_SIZE] = {0}; + uint8_t encoded_cell[RELAY_PAYLOAD_SIZE_MAX] = {0}; + uint8_t encoded_enc_cell[RELAY_PAYLOAD_SIZE_MAX] = {0}; uint8_t *encrypted = NULL; uint8_t mac[DIGEST256_LEN]; crypto_cipher_t *cipher = NULL; @@ -339,7 +339,7 @@ * ENCRYPTED_DATA and MAC length. */ encrypted_len = sizeof(data->client_kp->pubkey) + encoded_enc_cell_len + sizeof(mac); - tor_assert(encrypted_len < RELAY_PAYLOAD_SIZE); + tor_assert(encrypted_len < RELAY_PAYLOAD_SIZE_MAX); encrypted = tor_malloc_zero(encrypted_len); /* Put the CLIENT_PK first. */ @@ -369,7 +369,7 @@ /* Cleanup. */ memwipe(&keys, 0, sizeof(keys)); memwipe(mac, 0, sizeof(mac)); - memwipe(encrypted, 0, sizeof(encrypted_len)); + memwipe(encrypted, 0, encrypted_len); memwipe(encoded_enc_cell, 0, sizeof(encoded_enc_cell)); tor_free(encrypted); } @@ -709,7 +709,7 @@ ssize_t tmp_cell_mac_offset = sig_len + sizeof(cell->sig_len) + trn_cell_establish_intro_getlen_handshake_mac(cell); - uint8_t tmp_cell_enc[RELAY_PAYLOAD_SIZE] = {0}; + uint8_t tmp_cell_enc[RELAY_PAYLOAD_SIZE_MAX] = {0}; uint8_t mac[TRUNNEL_SHA3_256_LEN], *handshake_ptr; /* We first encode the current fields we have in the cell so we can @@ -738,7 +738,7 @@ { ssize_t tmp_cell_enc_len = 0; ssize_t tmp_cell_sig_offset = (sig_len + sizeof(cell->sig_len)); - uint8_t tmp_cell_enc[RELAY_PAYLOAD_SIZE] = {0}, *sig_ptr; + uint8_t tmp_cell_enc[RELAY_PAYLOAD_SIZE_MAX] = {0}, *sig_ptr; ed25519_signature_t sig; /* We first encode the current fields we have in the cell so we can @@ -764,7 +764,8 @@ } /* Encode the cell. Can't be bigger than a standard cell. */ - cell_len = trn_cell_establish_intro_encode(cell_out, RELAY_PAYLOAD_SIZE, + cell_len = trn_cell_establish_intro_encode(cell_out, + RELAY_PAYLOAD_SIZE_MAX, cell); done: @@ -1161,7 +1162,8 @@ memcpy(trn_cell_rendezvous1_getarray_handshake_info(cell), rendezvous_handshake_info, rendezvous_handshake_info_len); /* Encoding. */ - cell_len = trn_cell_rendezvous1_encode(cell_out, RELAY_PAYLOAD_SIZE, cell); + cell_len = trn_cell_rendezvous1_encode(cell_out, + RELAY_PAYLOAD_SIZE_MAX, cell); tor_assert(cell_len > 0); trn_cell_rendezvous1_free(cell); @@ -1200,7 +1202,8 @@ introduce1_set_encrypted(cell, data); /* Final encoding. */ - cell_len = trn_cell_introduce1_encode(cell_out, RELAY_PAYLOAD_SIZE, cell); + cell_len = trn_cell_introduce1_encode(cell_out, + RELAY_PAYLOAD_SIZE_MAX, cell); trn_cell_introduce1_free(cell); return cell_len; diff -Nru tor-0.4.8.16/src/feature/hs/hs_circuit.c tor-0.4.9.6/src/feature/hs/hs_circuit.c --- tor-0.4.8.16/src/feature/hs/hs_circuit.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs/hs_circuit.c 2026-03-25 14:30:34.000000000 +0000 @@ -110,8 +110,12 @@ cpath = tor_malloc_zero(sizeof(crypt_path_t)); cpath->magic = CRYPT_PATH_MAGIC; - if (cpath_init_circuit_crypto(cpath, (char*)keys, sizeof(keys), - is_service_side, 1) < 0) { + // TODO CGO: Pick relay cell format based on capabilities. + cpath->relay_cell_format = RELAY_CELL_FORMAT_V0; + relay_crypto_alg_t alg = is_service_side ? RELAY_CRYPTO_ALG_TOR1_HSS : + RELAY_CRYPTO_ALG_TOR1_HSC; + + if (cpath_init_circuit_crypto(alg, cpath, (char*)keys, sizeof(keys)) < 0) { tor_free(cpath); goto err; } @@ -268,7 +272,7 @@ hs_service_intro_point_t *ip, origin_circuit_t *circ) { ssize_t cell_len; - uint8_t payload[RELAY_PAYLOAD_SIZE]; + uint8_t payload[RELAY_PAYLOAD_SIZE_MAX]; tor_assert(service); tor_assert(ip); @@ -1153,7 +1157,7 @@ origin_circuit_t *circ) { size_t payload_len; - uint8_t payload[RELAY_PAYLOAD_SIZE] = {0}; + uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0}; tor_assert(service); tor_assert(circ); @@ -1442,7 +1446,7 @@ { int ret = -1; ssize_t payload_len; - uint8_t payload[RELAY_PAYLOAD_SIZE] = {0}; + uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0}; hs_cell_introduce1_data_t intro1_data; tor_assert(intro_circ); @@ -1526,7 +1530,7 @@ hs_circ_send_establish_rendezvous(origin_circuit_t *circ) { ssize_t cell_len = 0; - uint8_t cell[RELAY_PAYLOAD_SIZE] = {0}; + uint8_t cell[RELAY_PAYLOAD_SIZE_MAX] = {0}; tor_assert(circ); tor_assert(TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND); diff -Nru tor-0.4.8.16/src/feature/hs/hs_client.c tor-0.4.9.6/src/feature/hs/hs_client.c --- tor-0.4.8.16/src/feature/hs/hs_client.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs/hs_client.c 2026-03-25 14:30:34.000000000 +0000 @@ -1448,6 +1448,9 @@ err: circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); end: + memwipe(auth_mac, 0, sizeof(auth_mac)); + memwipe(handshake_info, 0, sizeof(handshake_info)); + memwipe(&server_pk, 0, sizeof(server_pk)); memwipe(&keys, 0, sizeof(keys)); return ret; } diff -Nru tor-0.4.8.16/src/feature/hs/hs_common.c tor-0.4.9.6/src/feature/hs/hs_common.c --- tor-0.4.8.16/src/feature/hs/hs_common.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs/hs_common.c 2026-03-25 14:30:34.000000000 +0000 @@ -1686,7 +1686,7 @@ /* We do have everything for which we think we can connect successfully. */ info = extend_info_new(NULL, legacy_id, - (have_ed25519_id) ? &ed25519_pk : NULL, NULL, + (have_ed25519_id) ? &ed25519_pk : NULL, onion_key, &ap.addr, ap.port, NULL, false); done: return info; diff -Nru tor-0.4.8.16/src/feature/hs/hs_common.h tor-0.4.9.6/src/feature/hs/hs_common.h --- tor-0.4.8.16/src/feature/hs/hs_common.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs/hs_common.h 2026-03-25 14:30:34.000000000 +0000 @@ -49,13 +49,6 @@ /** String prefix for the signature of ESTABLISH_INTRO */ #define ESTABLISH_INTRO_SIG_PREFIX "Tor establish-intro cell v1" -/** The default HS time period length */ -#define HS_TIME_PERIOD_LENGTH_DEFAULT 1440 /* 1440 minutes == one day */ -/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */ -#define HS_TIME_PERIOD_LENGTH_MIN 30 /* minutes */ -/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */ -#define HS_TIME_PERIOD_LENGTH_MAX (60 * 24 * 10) /* 10 days or 14400 minutes */ - /** Prefix of the onion address checksum. */ #define HS_SERVICE_ADDR_CHECKSUM_PREFIX ".onion checksum" /** Length of the checksum prefix minus the NUL terminated byte. */ @@ -83,7 +76,7 @@ /** The default HS time period length */ #define HS_TIME_PERIOD_LENGTH_DEFAULT 1440 /* 1440 minutes == one day */ /** The minimum time period length as seen in prop224 section [TIME-PERIODS] */ -#define HS_TIME_PERIOD_LENGTH_MIN 30 /* minutes */ +#define HS_TIME_PERIOD_LENGTH_MIN 5 /* minutes */ /** The minimum time period length as seen in prop224 section [TIME-PERIODS] */ #define HS_TIME_PERIOD_LENGTH_MAX (60 * 24 * 10) /* 10 days or 14400 minutes */ /** The time period rotation offset as seen in prop224 section diff -Nru tor-0.4.8.16/src/feature/hs/hs_config.h tor-0.4.9.6/src/feature/hs/hs_config.h --- tor-0.4.8.16/src/feature/hs/hs_config.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs/hs_config.h 2026-03-25 14:30:34.000000000 +0000 @@ -27,6 +27,8 @@ /* Default values for the HS anti-DoS PoW defenses. */ #define HS_CONFIG_V3_POW_DEFENSES_DEFAULT 0 +#define HS_CONFIG_V3_POW_QUEUE_RATE 250 +#define HS_CONFIG_V3_POW_QUEUE_BURST 2500 /* API */ diff -Nru tor-0.4.8.16/src/feature/hs/hs_descriptor.c tor-0.4.9.6/src/feature/hs/hs_descriptor.c --- tor-0.4.8.16/src/feature/hs/hs_descriptor.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs/hs_descriptor.c 2026-03-25 14:30:34.000000000 +0000 @@ -155,7 +155,7 @@ T01(str_intro_auth_required, R3_INTRO_AUTH_REQUIRED, GE(1), NO_OBJ), T01(str_single_onion, R3_SINGLE_ONION_SERVICE, ARGS, NO_OBJ), T01(str_flow_control, R3_FLOW_CONTROL, GE(2), NO_OBJ), - T01(str_pow_params, R3_POW_PARAMS, GE(4), NO_OBJ), + T0N(str_pow_params, R3_POW_PARAMS, GE(1), NO_OBJ), END_OF_TABLE }; @@ -2098,67 +2098,88 @@ return ret; } -/** Given the token tok for PoW params, decode it as hs_pow_desc_params_t. - * tok->args MUST contain at least 4 elements Return 0 on success else -1 on - * failure. */ +/** Given a list of tokens for PoW params, decode it as a v1 + * hs_pow_desc_params_t. + * + * Each token's args MUST contain at least 1 element. + * + * On success, return 0, and set pow_params_out to a new set of + * parameters (or to NULL if there were no v1 parameters). Return -1 on + * failure. + */ static int -decode_pow_params(const directory_token_t *tok, - hs_pow_desc_params_t *pow_params) +decode_pow_params(const smartlist_t *toks, + hs_pow_desc_params_t **pow_params_out) { + bool found_v1 = false; int ret = -1; + tor_assert(pow_params_out); + *pow_params_out = NULL; - tor_assert(tok); - tor_assert(tok->n_args >= 4); - tor_assert(pow_params); + if (!toks) + return 0; - /* Find the type of PoW system being used. */ - int match = 0; - for (int idx = 0; pow_types[idx].identifier; idx++) { - if (!strncmp(tok->args[0], pow_types[idx].identifier, - strlen(pow_types[idx].identifier))) { - pow_params->type = pow_types[idx].type; - match = 1; - break; + SMARTLIST_FOREACH_BEGIN(toks, const directory_token_t *, tok) { + tor_assert(tok->n_args >= 1); + + if (strcmp(tok->args[0], "v1")) { + // Unrecognized type; skip it. + continue; } - } - if (!match) { - log_warn(LD_REND, "Unknown PoW type from descriptor."); - goto done; - } - if (base64_decode((char *)pow_params->seed, sizeof(pow_params->seed), - tok->args[1], strlen(tok->args[1])) != - sizeof(pow_params->seed)) { - log_warn(LD_REND, "Unparseable seed %s in PoW params", - escaped(tok->args[1])); - goto done; - } + if (found_v1) { + log_warn(LD_REND, "Duplicate v1 PoW entries in descriptor."); + goto done; + } + found_v1 = true; + if (tok->n_args < 4) { + log_warn(LD_REND, "Insufficient arguments for v1 PoW entry."); + goto done; + } - int ok; - unsigned long effort = + hs_pow_desc_params_t *pow_params = tor_malloc_zero(sizeof(*pow_params)); + *pow_params_out = pow_params; + pow_params->type = HS_POW_DESC_V1; + + if (base64_decode((char *)pow_params->seed, sizeof(pow_params->seed), + tok->args[1], strlen(tok->args[1])) != + sizeof(pow_params->seed)) { + log_warn(LD_REND, "Unparseable seed %s in PoW params", + escaped(tok->args[1])); + goto done; + } + + int ok; + unsigned long effort = tor_parse_ulong(tok->args[2], 10, 0, UINT32_MAX, &ok, NULL); - if (!ok) { - log_warn(LD_REND, "Unparseable suggested effort %s in PoW params", - escaped(tok->args[2])); - goto done; - } - pow_params->suggested_effort = (uint32_t)effort; + if (!ok) { + log_warn(LD_REND, "Unparseable suggested effort %s in PoW params", + escaped(tok->args[2])); + goto done; + } + pow_params->suggested_effort = (uint32_t)effort; - /* Parse the expiration time of the PoW params. */ - time_t expiration_time = 0; - if (parse_iso_time_nospace(tok->args[3], &expiration_time)) { - log_warn(LD_REND, "Unparseable expiration time %s in PoW params", - escaped(tok->args[3])); - goto done; - } - /* Validation of this time is done in client_desc_has_arrived() so we can - * trigger a fetch if expired. */ - pow_params->expiration_time = expiration_time; + /* Parse the expiration time of the PoW params. */ + time_t expiration_time = 0; + if (parse_iso_time_nospace(tok->args[3], &expiration_time)) { + log_warn(LD_REND, "Unparseable expiration time %s in PoW params", + escaped(tok->args[3])); + goto done; + } + /* Validation of this time is done in client_desc_has_arrived() so we can + * trigger a fetch if expired. */ + pow_params->expiration_time = expiration_time; + + } SMARTLIST_FOREACH_END(tok); /* Success. */ ret = 0; done: + if (ret < 0 && *pow_params_out) { + tor_free(*pow_params_out); // sets it to NULL + } + return ret; } @@ -2474,15 +2495,13 @@ } /* Get PoW if any. */ - tok = find_opt_by_keyword(tokens, R3_POW_PARAMS); - if (tok) { - hs_pow_desc_params_t *pow_params = - tor_malloc_zero(sizeof(hs_pow_desc_params_t)); - if (decode_pow_params(tok, pow_params)) { - tor_free(pow_params); + { + smartlist_t *pow_toks = find_all_by_keyword(tokens, R3_POW_PARAMS); + int r = decode_pow_params(pow_toks, &desc_encrypted_out->pow_params); + smartlist_free(pow_toks); + if (r < 0) { goto err; } - desc_encrypted_out->pow_params = pow_params; } /* Initialize the descriptor's introduction point list before we start diff -Nru tor-0.4.8.16/src/feature/hs/hs_service.c tor-0.4.9.6/src/feature/hs/hs_service.c --- tor-0.4.8.16/src/feature/hs/hs_service.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs/hs_service.c 2026-03-25 14:30:34.000000000 +0000 @@ -264,7 +264,9 @@ c->intro_dos_rate_per_sec = HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_DEFAULT; c->intro_dos_burst_per_sec = HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT; /* PoW default options. */ - c->has_dos_defense_enabled = HS_CONFIG_V3_POW_DEFENSES_DEFAULT; + c->has_pow_defenses_enabled = HS_CONFIG_V3_POW_DEFENSES_DEFAULT; + c->pow_queue_rate = HS_CONFIG_V3_POW_QUEUE_RATE; + c->pow_queue_burst = HS_CONFIG_V3_POW_QUEUE_BURST; } /** Initialize PoW defenses */ @@ -410,11 +412,6 @@ static int32_t get_intro_point_min_lifetime(void) { -#define MIN_INTRO_POINT_LIFETIME_TESTING 10 - if (get_options()->TestingTorNetwork) { - return MIN_INTRO_POINT_LIFETIME_TESTING; - } - /* The [0, 2147483647] range is quite large to accommodate anything we decide * in the future. */ return networkstatus_get_param(NULL, "hs_intro_min_lifetime", @@ -427,11 +424,6 @@ static int32_t get_intro_point_max_lifetime(void) { -#define MAX_INTRO_POINT_LIFETIME_TESTING 30 - if (get_options()->TestingTorNetwork) { - return MAX_INTRO_POINT_LIFETIME_TESTING; - } - /* The [0, 2147483647] range is quite large to accommodate anything we decide * in the future. */ return networkstatus_get_param(NULL, "hs_intro_max_lifetime", @@ -2163,7 +2155,7 @@ continue; } - /* Reaching this point means we are pass bootup so at runtime. We should + /* Reaching this point means we are past bootup so at runtime. We should * *never* have an empty current descriptor. If the next descriptor is * empty, we'll try to build it for the next time period. This only * happens when we rotate meaning that we are guaranteed to have a new SRV @@ -2185,7 +2177,7 @@ /** Randomly pick a node to become an introduction point but not present in the * given exclude_nodes list. The chosen node is put in the exclude list * regardless of success or not because in case of failure, the node is simply - * unsusable from that point on. + * unusable from that point on. * * If direct_conn is set, try to pick a node that our local firewall/policy * allows us to connect to directly. If we can't find any, return NULL. @@ -3039,13 +3031,6 @@ tor_assert(service->config.num_intro_points <= HS_CONFIG_V3_MAX_INTRO_POINTS); -/** For a testing network, allow to do it for the maximum amount so circuit - * creation and rotation and so on can actually be tested without limit. */ -#define MAX_INTRO_POINT_CIRCUIT_RETRIES_TESTING -1 - if (get_options()->TestingTorNetwork) { - return MAX_INTRO_POINT_CIRCUIT_RETRIES_TESTING; - } - num_wanted_ip = service->config.num_intro_points; /* The calculation is as follow. We have a number of intro points that we @@ -3279,9 +3264,8 @@ } /** Encode and sign the service descriptor desc and upload it to the - * responsible hidden service directories. If for_next_period is true, the set - * of directories are selected using the next hsdir_index. This does nothing - * if PublishHidServDescriptors is false. */ + * responsible hidden service directories. + * This does nothing if PublishHidServDescriptors is false. */ STATIC void upload_descriptor_to_all(const hs_service_t *service, hs_service_descriptor_t *desc) @@ -4080,6 +4064,9 @@ hs_service_add_ephemeral(ed25519_secret_key_t *sk, smartlist_t *ports, int max_streams_per_rdv_circuit, int max_streams_close_circuit, + int pow_defenses_enabled, + uint32_t pow_queue_rate, + uint32_t pow_queue_burst, smartlist_t *auth_clients_v3, char **address_out) { hs_service_add_ephemeral_status_t ret; @@ -4099,6 +4086,9 @@ service->config.is_ephemeral = 1; smartlist_free(service->config.ports); service->config.ports = ports; + service->config.has_pow_defenses_enabled = pow_defenses_enabled; + service->config.pow_queue_rate = pow_queue_rate; + service->config.pow_queue_burst = pow_queue_burst; /* Handle the keys. */ memcpy(&service->keys.identity_sk, sk, sizeof(service->keys.identity_sk)); diff -Nru tor-0.4.8.16/src/feature/hs/hs_service.h tor-0.4.9.6/src/feature/hs/hs_service.h --- tor-0.4.8.16/src/feature/hs/hs_service.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs/hs_service.h 2026-03-25 14:30:34.000000000 +0000 @@ -113,7 +113,7 @@ digest256map_t *map; /** Contains node's identity key digest that were introduction point for this - * descriptor but were retried to many times. We keep those so we avoid + * descriptor but were retried too many times. We keep those so we avoid * re-picking them over and over for a circuit retry period. * XXX: Once we have #22173, change this to only use ed25519 identity. */ digestmap_t *failed_id; @@ -389,6 +389,9 @@ hs_service_add_ephemeral(ed25519_secret_key_t *sk, smartlist_t *ports, int max_streams_per_rdv_circuit, int max_streams_close_circuit, + int pow_defenses_enabled, + uint32_t pow_queue_rate, + uint32_t pow_queue_burst, smartlist_t *auth_clients_v3, char **address_out); int hs_service_del_ephemeral(const char *address); diff -Nru tor-0.4.8.16/src/feature/hs/include.am tor-0.4.9.6/src/feature/hs/include.am --- tor-0.4.8.16/src/feature/hs/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -1,6 +1,6 @@ # ADD_C_FILE: INSERT SOURCES HERE. -LIBTOR_APP_A_SOURCES += \ +LIBTOR_APP_A_SOURCES += \ src/feature/hs/hs_cache.c \ src/feature/hs/hs_cell.c \ src/feature/hs/hs_circuit.c \ @@ -13,11 +13,11 @@ src/feature/hs/hs_dos.c \ src/feature/hs/hs_ident.c \ src/feature/hs/hs_intropoint.c \ - src/feature/hs/hs_metrics.c \ + src/feature/hs/hs_metrics.c \ src/feature/hs/hs_ob.c \ src/feature/hs/hs_service.c \ src/feature/hs/hs_stats.c \ - src/feature/hs/hs_sys.c \ + src/feature/hs/hs_sys.c \ src/feature/hs/hs_metrics_entry.c # Proof of Work module @@ -42,7 +42,7 @@ src/feature/hs/hs_dos.h \ src/feature/hs/hs_ident.h \ src/feature/hs/hs_intropoint.h \ - src/feature/hs/hs_metrics.h \ + src/feature/hs/hs_metrics.h \ src/feature/hs/hs_ob.h \ src/feature/hs/hs_opts_st.h \ src/feature/hs/hs_options.inc \ @@ -50,5 +50,5 @@ src/feature/hs/hs_service.h \ src/feature/hs/hs_stats.h \ src/feature/hs/hsdir_index_st.h \ - src/feature/hs/hs_sys.h \ + src/feature/hs/hs_sys.h \ src/feature/hs/hs_metrics_entry.h diff -Nru tor-0.4.8.16/src/feature/hs_common/include.am tor-0.4.9.6/src/feature/hs_common/include.am --- tor-0.4.8.16/src/feature/hs_common/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/hs_common/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -1,7 +1,7 @@ # ADD_C_FILE: INSERT SOURCES HERE. LIBTOR_APP_A_SOURCES += \ - src/feature/hs_common/replaycache.c \ + src/feature/hs_common/replaycache.c \ src/feature/hs_common/shared_random_client.c # ADD_C_FILE: INSERT HEADERS HERE. diff -Nru tor-0.4.8.16/src/feature/metrics/include.am tor-0.4.9.6/src/feature/metrics/include.am --- tor-0.4.8.16/src/feature/metrics/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/metrics/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -1,10 +1,10 @@ # ADD_C_FILE: INSERT SOURCES HERE. -LIBTOR_APP_A_SOURCES += \ +LIBTOR_APP_A_SOURCES += \ src/feature/metrics/metrics.c \ src/feature/metrics/metrics_sys.c # ADD_C_FILE: INSERT HEADERS HERE. -noinst_HEADERS += \ +noinst_HEADERS += \ src/feature/metrics/metrics.h \ src/feature/metrics/metrics_sys.h diff -Nru tor-0.4.8.16/src/feature/nodelist/include.am tor-0.4.9.6/src/feature/nodelist/include.am --- tor-0.4.8.16/src/feature/nodelist/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/nodelist/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -1,6 +1,6 @@ # ADD_C_FILE: INSERT SOURCES HERE. -LIBTOR_APP_A_SOURCES += \ +LIBTOR_APP_A_SOURCES += \ src/feature/nodelist/authcert.c \ src/feature/nodelist/describe.c \ src/feature/nodelist/dirlist.c \ @@ -30,7 +30,7 @@ src/feature/nodelist/networkstatus.h \ src/feature/nodelist/networkstatus_sr_info_st.h \ src/feature/nodelist/networkstatus_st.h \ - src/feature/nodelist/networkstatus_voter_info_st.h \ + src/feature/nodelist/networkstatus_voter_info_st.h\ src/feature/nodelist/nickname.h \ src/feature/nodelist/node_st.h \ src/feature/nodelist/nodefamily.h \ diff -Nru tor-0.4.8.16/src/feature/nodelist/microdesc.c tor-0.4.9.6/src/feature/nodelist/microdesc.c --- tor-0.4.8.16/src/feature/nodelist/microdesc.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/nodelist/microdesc.c 2026-03-25 14:30:34.000000000 +0000 @@ -909,14 +909,16 @@ //tor_assert(md->held_in_map == 0); //tor_assert(md->held_by_nodes == 0); - if (md->onion_pkey) - tor_free(md->onion_pkey); tor_free(md->onion_curve25519_pkey); tor_free(md->ed25519_identity_pkey); if (md->body && md->saved_location != SAVED_IN_CACHE) tor_free(md->body); nodefamily_free(md->family); + if (md->family_ids) { + SMARTLIST_FOREACH(md->family_ids, char *, cp, tor_free(cp)); + smartlist_free(md->family_ids); + } short_policy_free(md->exit_policy); short_policy_free(md->ipv6_exit_policy); diff -Nru tor-0.4.8.16/src/feature/nodelist/microdesc_st.h tor-0.4.9.6/src/feature/nodelist/microdesc_st.h --- tor-0.4.8.16/src/feature/nodelist/microdesc_st.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/nodelist/microdesc_st.h 2026-03-25 14:30:34.000000000 +0000 @@ -16,6 +16,7 @@ struct ed25519_public_key_t; struct nodefamily_t; struct short_policy_t; +struct smartlist_t; #include "ext/ht.h" @@ -63,14 +64,6 @@ /* Fields in the microdescriptor. */ - /** - * Public RSA TAP key for onions, ASN.1 encoded. We store this - * in its encoded format since storing it as a crypto_pk_t uses - * significantly more memory. */ - char *onion_pkey; - /** Length of onion_pkey, in bytes. */ - size_t onion_pkey_len; - /** As routerinfo_t.onion_curve25519_pkey */ struct curve25519_public_key_t *onion_curve25519_pkey; /** Ed25519 identity key, if included. */ @@ -81,6 +74,11 @@ uint16_t ipv6_orport; /** As routerinfo_t.family, with readable members parsed. */ struct nodefamily_t *family; + /** A list of strings representing router family IDs. + * May be null; Copied from family-ids. + * (Happy families only.) */ + struct smartlist_t *family_ids; + /** IPv4 exit policy summary */ struct short_policy_t *exit_policy; /** IPv6 exit policy summary */ diff -Nru tor-0.4.8.16/src/feature/nodelist/networkstatus.c tor-0.4.9.6/src/feature/nodelist/networkstatus.c --- tor-0.4.8.16/src/feature/nodelist/networkstatus.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/nodelist/networkstatus.c 2026-03-25 14:30:34.000000000 +0000 @@ -1954,7 +1954,7 @@ int free_consensus = 1; /* Free 'c' at the end of the function */ int checked_protocols_already = 0; - if (flav < 0) { + if (flav < 0 || flav >= N_CONSENSUS_FLAVORS) { /* XXXX we don't handle unrecognized flavors yet. */ log_warn(LD_BUG, "Unrecognized consensus flavor %s", flavor); return -2; @@ -1982,6 +1982,7 @@ if ((int)c->flavor != flav) { /* This wasn't the flavor we thought we were getting. */ + tor_assert(c->flavor < N_CONSENSUS_FLAVORS); if (require_flavor) { log_warn(LD_DIR, "Got consensus with unexpected flavor %s (wanted %s)", networkstatus_get_flavor_name(c->flavor), flavor); @@ -2140,6 +2141,10 @@ } current_md_consensus = c; free_consensus = 0; /* avoid free */ + } else { + tor_assert_nonfatal_unreached(); + result = -2; + goto done; } waiting = &consensus_waiting_for_certs[flav]; diff -Nru tor-0.4.8.16/src/feature/nodelist/node_select.h tor-0.4.9.6/src/feature/nodelist/node_select.h --- tor-0.4.8.16/src/feature/nodelist/node_select.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/nodelist/node_select.h 2026-03-25 14:30:34.000000000 +0000 @@ -29,7 +29,7 @@ /* On clients, if choosing a node for a direct connection, only provide * nodes that satisfy ClientPreferIPv6OR. */ CRN_PREF_ADDR = 1<<5, - /* On clients, indiate that we need a HS related circuit (IP, HSDir or RP). + /* On clients, indicate that we need a HS related circuit (IP, HSDir, or RP). * This is used in order to avoid certain nodes for these purposes. */ CRN_FOR_HS = 1<<6, /* On clients, only provide nodes that can initiate IPv6 extends. */ diff -Nru tor-0.4.8.16/src/feature/nodelist/nodelist.c tor-0.4.9.6/src/feature/nodelist/nodelist.c --- tor-0.4.8.16/src/feature/nodelist/nodelist.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/nodelist/nodelist.c 2026-03-25 14:30:34.000000000 +0000 @@ -680,6 +680,32 @@ return ESTIMATED_ADDRESS_PER_NODE; } +/** + * If true, we use relays' listed family members in order to + * determine which relays are in the same family. + */ +static int use_family_lists = 1; +/** + * If true, we use relays' validated family IDs in order to + * determine which relays are in the same family. + */ +static int use_family_ids = 1; + +/** + * Update consensus parameters relevant to nodelist operations. + * + * We need to cache these values rather than searching for them every time + * we check whether two relays are in the same family. + **/ +static void +nodelist_update_consensus_params(const networkstatus_t *ns) +{ + use_family_lists = networkstatus_get_param(ns, "use-family-lists", + 1, 0, 1); // default, low, high + use_family_ids = networkstatus_get_param(ns, "use-family-ids", + 1, 0, 1); // default, low, high +} + /** Tell the nodelist that the current usable consensus is ns. * This makes the nodelist change all of the routerstatus entries for * the nodes, drop nodes that no longer have enough info to get used, @@ -698,6 +724,8 @@ SMARTLIST_FOREACH(the_nodelist->nodes, node_t *, node, node->rs = NULL); + nodelist_update_consensus_params(ns); + /* Conservatively estimate that every node will have 2 addresses (v4 and * v6). Then we add the number of configured trusted authorities we have. */ int estimated_addresses = smartlist_len(ns->routerstatus_list) * @@ -733,15 +761,21 @@ } node_set_country(node); - /* If we're not an authdir, believe others. */ - if (!authdir) { + /* Set node's flags based on rs's flags. */ + { node->is_valid = rs->is_valid; node->is_running = rs->is_flagged_running; node->is_fast = rs->is_fast; node->is_stable = rs->is_stable; node->is_possible_guard = rs->is_possible_guard; node->is_exit = rs->is_exit; - node->is_bad_exit = rs->is_bad_exit; + if (!authdir) { + /* Authdirs treat is_bad_exit specially in that they only assign + * it when the descriptor arrives. So when a dir auth is reading + * the flags from an existing consensus, don't believe the bit + * here, else it will get stuck 'on' forever. */ + node->is_bad_exit = rs->is_bad_exit; + } node->is_hs_dir = rs->is_hs_dir; node->ipv6_preferred = 0; if (reachable_addr_prefer_ipv6_orport(options) && @@ -787,15 +821,6 @@ } } -/** Return 1 iff node has Exit flag and no BadExit flag. - * Otherwise, return 0. - */ -int -node_is_good_exit(const node_t *node) -{ - return node->is_exit && ! node->is_bad_exit; -} - /** Helper: return true iff a node has a usable amount of information*/ static inline int node_is_usable(const node_t *node) @@ -1205,7 +1230,7 @@ /** Dummy object that should be unreturnable. Used to ensure that * node_get_protover_summary_flags() always returns non-NULL. */ static const protover_summary_flags_t zero_protover_flags = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0 + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; /** Return the protover_summary_flags for a given node. */ @@ -1473,13 +1498,13 @@ node_is_dir(const node_t *node) { if (node->rs) { - routerstatus_t * rs = node->rs; + routerstatus_t *rs = node->rs; /* This is true if supports_tunnelled_dir_requests is true which * indicates that we support directory request tunnelled or through the * DirPort. */ return rs->is_v2_dir; } else if (node->ri) { - routerinfo_t * ri = node->ri; + routerinfo_t *ri = node->ri; /* Both tunnelled request is supported or DirPort is set. */ return ri->supports_tunnelled_dir_requests; } else { @@ -2034,37 +2059,6 @@ return NULL; } -/* Return a newly allocacted RSA onion public key taken from the given node. - * - * Return NULL if node is NULL or no RSA onion public key can be found. It is - * the caller responsibility to free the returned object. */ -crypto_pk_t * -node_get_rsa_onion_key(const node_t *node) -{ - crypto_pk_t *pk = NULL; - const char *onion_pkey; - size_t onion_pkey_len; - - if (!node) { - goto end; - } - - if (node->ri) { - onion_pkey = node->ri->onion_pkey; - onion_pkey_len = node->ri->onion_pkey_len; - } else if (node->rs && node->md) { - onion_pkey = node->md->onion_pkey; - onion_pkey_len = node->md->onion_pkey_len; - } else { - /* No descriptor or microdescriptor. */ - goto end; - } - pk = router_get_rsa_onion_pkey(onion_pkey, onion_pkey_len); - - end: - return pk; -} - /** Refresh the country code of ri. This function MUST be called on * each router when the GeoIP database is reloaded, and on all new routers. */ void @@ -2145,7 +2139,7 @@ /** Return true iff n1's declared family contains n2. */ STATIC int -node_family_contains(const node_t *n1, const node_t *n2) +node_family_list_contains(const node_t *n1, const node_t *n2) { if (n1->ri && n1->ri->declared_family) { return node_in_nickname_smartlist(n1->ri->declared_family, n2); @@ -2160,7 +2154,7 @@ * Return true iff node has declared a nonempty family. **/ STATIC bool -node_has_declared_family(const node_t *node) +node_has_declared_family_list(const node_t *node) { if (node->ri && node->ri->declared_family && smartlist_len(node->ri->declared_family)) { @@ -2175,12 +2169,44 @@ } /** + * Return the listed family IDs of `a`, if it has any. + */ +static const smartlist_t * +node_get_family_ids(const node_t *node) +{ + if (node->ri && node->ri->family_ids) { + return node->ri->family_ids; + } else if (node->md && node->md->family_ids) { + return node->md->family_ids; + } else { + return NULL; + } +} + +/** + * Return true iff `a` and `b` have any family ID in common. + **/ +static bool +nodes_have_common_family_id(const node_t *a, const node_t *b) +{ + const smartlist_t *ids_a = node_get_family_ids(a); + const smartlist_t *ids_b = node_get_family_ids(b); + if (ids_a == NULL || ids_b == NULL) + return false; + SMARTLIST_FOREACH(ids_a, const char *, id, { + if (smartlist_contains_string(ids_b, id)) + return true; + }); + return false; +} + +/** * Add to out every node_t that is listed by node as being in * its family. (Note that these nodes are not in node's family unless they * also agree that node is in their family.) **/ STATIC void -node_lookup_declared_family(smartlist_t *out, const node_t *node) +node_lookup_declared_family_list(smartlist_t *out, const node_t *node) { if (node->ri && node->ri->declared_family && smartlist_len(node->ri->declared_family)) { @@ -2220,9 +2246,17 @@ return 1; } - /* Are they in the same family because the agree they are? */ - if (node_family_contains(node1, node2) && - node_family_contains(node2, node1)) { + /* Are they in the same family because they agree they are? */ + if (use_family_lists && + node_family_list_contains(node1, node2) && + node_family_list_contains(node2, node1)) { + return 1; + } + + /* Are they in the same family because they have a common + * verified family ID? */ + if (use_family_ids && + nodes_have_common_family_id(node1, node2)) { return 1; } @@ -2282,20 +2316,31 @@ /* Now, add all nodes in the declared family of this node, if they * also declare this node to be in their family. */ - if (node_has_declared_family(node)) { + if (use_family_lists && + node_has_declared_family_list(node)) { smartlist_t *declared_family = smartlist_new(); - node_lookup_declared_family(declared_family, node); + node_lookup_declared_family_list(declared_family, node); /* Add every r such that router declares familyness with node, and node * declares familyhood with router. */ SMARTLIST_FOREACH_BEGIN(declared_family, const node_t *, node2) { - if (node_family_contains(node2, node)) { + if (node_family_list_contains(node2, node)) { smartlist_add(sl, (void*)node2); } } SMARTLIST_FOREACH_END(node2); smartlist_free(declared_family); } + /* Now add all the nodes that share a verified family ID with this node. */ + if (use_family_ids && + node_get_family_ids(node)) { + SMARTLIST_FOREACH(all_nodes, const node_t *, node2, { + if (nodes_have_common_family_id(node, node2)) { + smartlist_add(sl, (void *)node2); + } + }); + } + /* If the user declared any families locally, honor those too. */ if (options->NodeFamilySets) { SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, { diff -Nru tor-0.4.8.16/src/feature/nodelist/nodelist.h tor-0.4.9.6/src/feature/nodelist/nodelist.h --- tor-0.4.8.16/src/feature/nodelist/nodelist.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/nodelist/nodelist.h 2026-03-25 14:30:34.000000000 +0000 @@ -54,7 +54,6 @@ void node_get_verbose_nickname_by_id(const char *id_digest, char *verbose_name_out); int node_is_dir(const node_t *node); -int node_is_good_exit(const node_t *node); int node_has_any_descriptor(const node_t *node); int node_has_preferred_descriptor(const node_t *node, int for_direct_connect); @@ -109,7 +108,6 @@ int node_has_curve25519_onion_key(const node_t *node); const struct curve25519_public_key_t *node_get_curve25519_onion_key( const node_t *node); -crypto_pk_t *node_get_rsa_onion_key(const node_t *node); MOCK_DECL(const smartlist_t *, nodelist_get_list, (void)); @@ -171,9 +169,10 @@ STATIC int node_nickname_matches(const node_t *node, const char *nickname); STATIC int node_in_nickname_smartlist(const smartlist_t *lst, const node_t *node); -STATIC int node_family_contains(const node_t *n1, const node_t *n2); -STATIC bool node_has_declared_family(const node_t *node); -STATIC void node_lookup_declared_family(smartlist_t *out, const node_t *node); +STATIC int node_family_list_contains(const node_t *n1, const node_t *n2); +STATIC bool node_has_declared_family_list(const node_t *node); +STATIC void node_lookup_declared_family_list(smartlist_t *out, + const node_t *node); #ifdef TOR_UNIT_TESTS diff -Nru tor-0.4.8.16/src/feature/nodelist/routerinfo_st.h tor-0.4.9.6/src/feature/nodelist/routerinfo_st.h --- tor-0.4.8.16/src/feature/nodelist/routerinfo_st.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/nodelist/routerinfo_st.h 2026-03-25 14:30:34.000000000 +0000 @@ -15,6 +15,7 @@ #include "feature/nodelist/signed_descriptor_st.h" struct curve25519_public_key_t; +struct smartlist_t; /** Information about another onion router in the network. */ struct routerinfo_t { @@ -33,10 +34,13 @@ /** * Public RSA TAP key for onions, ASN.1 encoded. We store this * in its encoded format since storing it as a crypto_pk_t uses - * significantly more memory. */ - char *onion_pkey; + * significantly more memory. + * + * This may be absent. + */ + char *tap_onion_pkey; /** Length of onion_pkey, in bytes. */ - size_t onion_pkey_len; + size_t tap_onion_pkey_len; crypto_pk_t *identity_pkey; /**< Public RSA key for signing. */ /** Public curve25519 key for onions */ @@ -64,6 +68,10 @@ long uptime; /**< How many seconds the router claims to have been up */ smartlist_t *declared_family; /**< Nicknames of router which this router * claims are its family. */ + /** A list of strings representing router family IDs. + * May be null. Extracted from family-certs. + * (Happy families only.) */ + struct smartlist_t *family_ids; char *contact_info; /**< Declared contact info for this router. */ unsigned int is_hibernating:1; /**< Whether the router claims to be * hibernating */ diff -Nru tor-0.4.8.16/src/feature/nodelist/routerlist.c tor-0.4.9.6/src/feature/nodelist/routerlist.c --- tor-0.4.8.16/src/feature/nodelist/routerlist.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/nodelist/routerlist.c 2026-03-25 14:30:34.000000000 +0000 @@ -600,7 +600,7 @@ return false; if (initiate_ipv6_extend && !node_supports_initiating_ipv6_extends(node)) return false; - /* MiddleOnly node should never be used for HS ndpoints (IP, RP, HSDir). */ + /* MiddleOnly node should never be used for HS endpoints (IP, RP, HSDir). */ if (for_hs && node->is_middle_only) { return false; } @@ -929,8 +929,8 @@ tor_free(router->platform); tor_free(router->protocol_list); tor_free(router->contact_info); - if (router->onion_pkey) - tor_free(router->onion_pkey); + if (router->tap_onion_pkey) + tor_free(router->tap_onion_pkey); tor_free(router->onion_curve25519_pkey); if (router->identity_pkey) crypto_pk_free(router->identity_pkey); @@ -939,6 +939,10 @@ SMARTLIST_FOREACH(router->declared_family, char *, s, tor_free(s)); smartlist_free(router->declared_family); } + if (router->family_ids) { + SMARTLIST_FOREACH(router->family_ids, char *, cp, tor_free(cp)); + smartlist_free(router->family_ids); + } addr_policy_list_free(router->exit_policy); short_policy_free(router->ipv6_exit_policy); @@ -2956,6 +2960,24 @@ /** We allow uptime to vary from how much it ought to be by this much. */ #define ROUTER_ALLOW_UPTIME_DRIFT (6*60*60) +/** Return true iff r1 and r2 have the same TAP onion keys. */ +static int +router_tap_onion_keys_eq(const routerinfo_t *r1, const routerinfo_t *r2) +{ + if (r1->tap_onion_pkey_len != r2->tap_onion_pkey_len) + return 0; + + if ((r1->tap_onion_pkey == NULL) && (r2->tap_onion_pkey == NULL)) { + return 1; + } else if ((r1->tap_onion_pkey != NULL) && (r2->tap_onion_pkey != NULL)) { + return tor_memeq(r1->tap_onion_pkey, r2->tap_onion_pkey, + r1->tap_onion_pkey_len); + } else { + /* One is NULL; one is not. */ + return 0; + } +} + /** Return true iff the only differences between r1 and r2 are such that * would not cause a recent (post 0.1.1.6) dirserver to republish. */ @@ -2981,8 +3003,7 @@ r1->ipv6_orport != r2->ipv6_orport || r1->ipv4_dirport != r2->ipv4_dirport || r1->purpose != r2->purpose || - r1->onion_pkey_len != r2->onion_pkey_len || - !tor_memeq(r1->onion_pkey, r2->onion_pkey, r1->onion_pkey_len) || + !router_tap_onion_keys_eq(r1,r2) || !crypto_pk_eq_keys(r1->identity_pkey, r2->identity_pkey) || strcasecmp(r1->platform, r2->platform) || (r1->contact_info && !r2->contact_info) || /* contact_info is optional */ diff -Nru tor-0.4.8.16/src/feature/nodelist/torcert.h tor-0.4.9.6/src/feature/nodelist/torcert.h --- tor-0.4.8.16/src/feature/nodelist/torcert.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/nodelist/torcert.h 2026-03-25 14:30:34.000000000 +0000 @@ -22,6 +22,7 @@ #define CERT_TYPE_AUTH_HS_IP_KEY 0x09 #define CERT_TYPE_ONION_ID 0x0A #define CERT_TYPE_CROSS_HS_IP_KEYS 0x0B +#define CERT_TYPE_FAMILY_V_IDENTITY 0x0C #define CERT_FLAG_INCLUDE_SIGNING_KEY 0x1 diff -Nru tor-0.4.8.16/src/feature/relay/circuitbuild_relay.c tor-0.4.9.6/src/feature/relay/circuitbuild_relay.c --- tor-0.4.8.16/src/feature/relay/circuitbuild_relay.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/circuitbuild_relay.c 2026-03-25 14:30:34.000000000 +0000 @@ -389,7 +389,6 @@ circ->n_hop = extend_info_new(NULL /*nickname*/, (const char*)ec->node_id, &ec->ed_pubkey, - NULL, /*onion_key*/ NULL, /*curve25519_key*/ &chosen_ap->addr, chosen_ap->port, @@ -422,15 +421,14 @@ * Return -1 if we want to warn and tear down the circuit, else return 0. */ int -circuit_extend(struct cell_t *cell, struct circuit_t *circ) +circuit_extend(const relay_msg_t *rmsg, struct circuit_t *circ) { channel_t *n_chan; - relay_header_t rh; extend_cell_t ec; const char *msg = NULL; int should_launch = 0; - IF_BUG_ONCE(!cell) { + IF_BUG_ONCE(!rmsg) { return -1; } @@ -441,11 +439,13 @@ if (circuit_extend_state_valid_helper(circ) < 0) return -1; - relay_header_unpack(&rh, cell->payload); + /* We no longer accept EXTEND messages; only EXTEND2. */ + if (rmsg->command == RELAY_COMMAND_EXTEND) { + /* TODO: Should we log this? */ + return -1; + } - if (extend_cell_parse(&ec, rh.command, - cell->payload+RELAY_HEADER_SIZE, - rh.length) < 0) { + if (extend_cell_parse(&ec, rmsg->command, rmsg->body, rmsg->length) < 0) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Can't parse extend cell. Closing circuit."); return -1; @@ -535,6 +535,7 @@ int onionskin_answer(struct or_circuit_t *circ, const created_cell_t *created_cell, + relay_crypto_alg_t crypto_alg, const char *keys, size_t keys_len, const uint8_t *rend_circ_nonce) { @@ -556,8 +557,6 @@ return -1; } - tor_assert(keys_len == CPATH_KEY_MATERIAL_LEN); - if (created_cell_format(&cell, created_cell) < 0) { log_warn(LD_BUG,"couldn't format created cell (type=%d, len=%d).", (int)created_cell->cell_type, (int)created_cell->handshake_len); @@ -567,10 +566,8 @@ circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN); - log_debug(LD_CIRC,"init digest forward 0x%.8x, backward 0x%.8x.", - (unsigned int)get_uint32(keys), - (unsigned int)get_uint32(keys+20)); - if (relay_crypto_init(&circ->crypto, keys, keys_len, 0, 0)<0) { + if (relay_crypto_init(crypto_alg, + &circ->crypto, keys, keys_len)<0) { log_warn(LD_BUG,"Circuit initialization failed."); return -1; } diff -Nru tor-0.4.8.16/src/feature/relay/circuitbuild_relay.h tor-0.4.9.6/src/feature/relay/circuitbuild_relay.h --- tor-0.4.8.16/src/feature/relay/circuitbuild_relay.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/circuitbuild_relay.h 2026-03-25 14:30:34.000000000 +0000 @@ -14,6 +14,8 @@ #include "lib/cc/torint.h" #include "lib/log/log.h" +#include "core/or/relay_msg_st.h" +#include "core/crypto/relay_crypto.h" #include "app/config/config.h" @@ -34,19 +36,20 @@ #ifdef HAVE_MODULE_RELAY -int circuit_extend(struct cell_t *cell, struct circuit_t *circ); +int circuit_extend(const relay_msg_t *msg, struct circuit_t *circ); int onionskin_answer(struct or_circuit_t *circ, const struct created_cell_t *created_cell, + relay_crypto_alg_t crypto_alg, const char *keys, size_t keys_len, const uint8_t *rend_circ_nonce); #else /* !defined(HAVE_MODULE_RELAY) */ static inline int -circuit_extend(struct cell_t *cell, struct circuit_t *circ) +circuit_extend(const relay_msg_t *msg, struct circuit_t *circ) { - (void)cell; + (void)msg; (void)circ; circuitbuild_warn_client_extend(); return -1; @@ -55,11 +58,13 @@ static inline int onionskin_answer(struct or_circuit_t *circ, const struct created_cell_t *created_cell, + relay_crypto_alg_t crypto_alg, const char *keys, size_t keys_len, const uint8_t *rend_circ_nonce) { (void)circ; (void)created_cell; + (void)crypto_alg; (void)keys; (void)keys_len; (void)rend_circ_nonce; diff -Nru tor-0.4.8.16/src/feature/relay/dns.c tor-0.4.9.6/src/feature/relay/dns.c --- tor-0.4.8.16/src/feature/relay/dns.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/dns.c 2026-03-25 14:30:34.000000000 +0000 @@ -86,6 +86,13 @@ * that the resolver is wedged? */ #define RESOLVE_MAX_TIMEOUT 300 +/** The clipped TTL sent back in the RESOLVED cell for every DNS queries. + * + * See https://gitlab.torproject.org/tpo/core/tor/-/issues/40979 for a thorough + * explanation but this is first and foremost a security fix in order to avoid + * an exit DNS cache oracle. */ +#define RESOLVED_CLIPPED_TTL (60) + /** Our evdns_base; this structure handles all our name lookups. */ static struct evdns_base *the_evdns_base = NULL; @@ -508,12 +515,13 @@ send_resolved_cell,(edge_connection_t *conn, uint8_t answer_type, const cached_resolve_t *resolved)) { - char buf[RELAY_PAYLOAD_SIZE], *cp = buf; + // (We use the minimum here to ensure that we never + // generate a too-big message.) + char buf[RELAY_PAYLOAD_SIZE_MIN], *cp = buf; size_t buflen = 0; - uint32_t ttl; + uint32_t ttl = RESOLVED_CLIPPED_TTL; buf[0] = answer_type; - ttl = conn->address_ttl; switch (answer_type) { @@ -563,6 +571,12 @@ connection_edge_send_command(conn, RELAY_COMMAND_RESOLVED, buf, buflen); } +void +dns_send_resolved_error_cell(edge_connection_t *conn, uint8_t answer_type) +{ + send_resolved_cell(conn, answer_type, NULL); +} + /** Send a response to the RESOLVE request of a connection for an in-addr.arpa * address on connection conn which yielded the result hostname. * The answer type will be RESOLVED_HOSTNAME. @@ -575,17 +589,18 @@ send_resolved_hostname_cell,(edge_connection_t *conn, const char *hostname)) { - char buf[RELAY_PAYLOAD_SIZE]; + char buf[RELAY_PAYLOAD_SIZE_MAX]; size_t buflen; - uint32_t ttl; + uint32_t ttl = RESOLVED_CLIPPED_TTL; if (BUG(!hostname)) return; size_t namelen = strlen(hostname); - tor_assert(namelen < 256); - ttl = conn->address_ttl; + if (BUG(namelen >= 256)) { + return; + } buf[0] = RESOLVED_TYPE_HOSTNAME; buf[1] = (uint8_t)namelen; @@ -1178,8 +1193,8 @@ * resolution. * * Do this by sending a RELAY_RESOLVED cell (if the pending stream had sent us - * RELAY_RESOLVE cell), or by launching an exit connection (if the pending - * stream had send us a RELAY_BEGIN cell). + * a RELAY_RESOLVE cell), or by launching an exit connection (if the pending + * stream had sent us a RELAY_BEGIN cell). */ static void inform_pending_connections(cached_resolve_t *resolve) diff -Nru tor-0.4.8.16/src/feature/relay/dns.h tor-0.4.9.6/src/feature/relay/dns.h --- tor-0.4.8.16/src/feature/relay/dns.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/dns.h 2026-03-25 14:30:34.000000000 +0000 @@ -20,6 +20,8 @@ void connection_dns_remove(edge_connection_t *conn); void assert_connection_edge_not_dns_pending(edge_connection_t *conn); int dns_resolve(edge_connection_t *exitconn); +void dns_send_resolved_error_cell(edge_connection_t *conn, + uint8_t answer_type); int dns_seems_to_be_broken(void); int dns_seems_to_be_broken_for_ipv6(void); void dns_reset_correctness_checks(void); @@ -36,6 +38,8 @@ #else /* !defined(HAVE_MODULE_RELAY) */ #define dns_init() (0) +#define dns_send_resolved_error_cell(conn, answer_type) \ + ((void)(conn), (void)(answer_type)) #define dns_seems_to_be_broken() (0) #define has_dns_init_failed() (0) #define dns_cache_total_allocation() (0) diff -Nru tor-0.4.8.16/src/feature/relay/ext_orport.c tor-0.4.9.6/src/feature/relay/ext_orport.c --- tor-0.4.8.16/src/feature/relay/ext_orport.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/ext_orport.c 2026-03-25 14:30:34.000000000 +0000 @@ -285,6 +285,9 @@ EXT_OR_PORT_AUTH_NONCE_LEN); } + memwipe(server_hash, 0, sizeof(server_hash)); + memwipe(server_nonce, 0, sizeof(server_nonce)); + *reply_out = reply; *reply_len_out = reply_len; diff -Nru tor-0.4.8.16/src/feature/relay/include.am tor-0.4.9.6/src/feature/relay/include.am --- tor-0.4.8.16/src/feature/relay/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -11,7 +11,7 @@ MODULE_RELAY_SOURCES = \ src/feature/relay/circuitbuild_relay.c \ src/feature/relay/dns.c \ - src/feature/relay/ext_orport.c \ + src/feature/relay/ext_orport.c \ src/feature/relay/routermode.c \ src/feature/relay/relay_config.c \ src/feature/relay/relay_handshake.c \ @@ -31,7 +31,7 @@ src/feature/relay/onion_queue.h \ src/feature/relay/relay_config.h \ src/feature/relay/relay_handshake.h \ - src/feature/relay/relay_metrics.h \ + src/feature/relay/relay_metrics.h \ src/feature/relay/relay_periodic.h \ src/feature/relay/relay_sys.h \ src/feature/relay/relay_find_addr.h \ diff -Nru tor-0.4.8.16/src/feature/relay/onion_queue.c tor-0.4.9.6/src/feature/relay/onion_queue.c --- tor-0.4.8.16/src/feature/relay/onion_queue.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/onion_queue.c 2026-03-25 14:30:34.000000000 +0000 @@ -50,10 +50,6 @@ #define ONION_QUEUE_MAX_DELAY_MIN 1 #define ONION_QUEUE_MAX_DELAY_MAX INT32_MAX -#define NUM_NTORS_PER_TAP_DEFAULT 10 -#define NUM_NTORS_PER_TAP_MIN 1 -#define NUM_NTORS_PER_TAP_MAX 100000 - /** Type for a linked list of circuits that are waiting for a free CPU worker * to process a waiting onion handshake. */ typedef struct onion_queue_t { @@ -84,17 +80,9 @@ static void onion_queue_entry_remove(onion_queue_t *victim); /** Consensus parameters. */ -static int32_t ns_num_ntors_per_tap = NUM_NTORS_PER_TAP_DEFAULT; static time_t ns_onion_queue_wait_cutoff = ONION_QUEUE_WAIT_CUTOFF_DEFAULT; static uint32_t ns_onion_queue_max_delay = ONION_QUEUE_MAX_DELAY_DEFAULT; -/** Return the number of ntors per tap from the cached parameter. */ -static inline int32_t -get_num_ntors_per_tap(void) -{ - return ns_num_ntors_per_tap; -} - /** Return the onion queue wait cutoff value from the cached parameter. */ static inline time_t get_onion_queue_wait_cutoff(void) @@ -146,8 +134,12 @@ const or_options_t *options = get_options(); int num_cpus; uint64_t max_onion_queue_delay; - uint64_t tap_usec, ntor_usec; - uint64_t ntor_during_tap_usec, tap_during_ntor_usec; + uint64_t ntor_usec; + + /* We never allow TAP. */ + if (type == ONION_HANDSHAKE_TYPE_TAP) { + return 0; + } /* If we've got fewer than 50 entries, we always have room for one more. */ if (ol_entries[type] < 50) @@ -164,44 +156,15 @@ /* Compute how many microseconds we'd expect to need to clear all * onionskins in various combinations of the queues. */ - /* How long would it take to process all the TAP cells in the queue? */ - tap_usec = estimated_usec_for_onionskins( - ol_entries[ONION_HANDSHAKE_TYPE_TAP], - ONION_HANDSHAKE_TYPE_TAP) / num_cpus; - /* How long would it take to process all the NTor cells in the queue? */ ntor_usec = estimated_usec_for_onionskins( ol_entries[ONION_HANDSHAKE_TYPE_NTOR], ONION_HANDSHAKE_TYPE_NTOR) / num_cpus; - /* How long would it take to process the tap cells that we expect to - * process while draining the ntor queue? */ - tap_during_ntor_usec = estimated_usec_for_onionskins( - MIN(ol_entries[ONION_HANDSHAKE_TYPE_TAP], - ol_entries[ONION_HANDSHAKE_TYPE_NTOR] / get_num_ntors_per_tap()), - ONION_HANDSHAKE_TYPE_TAP) / num_cpus; - - /* How long would it take to process the ntor cells that we expect to - * process while draining the tap queue? */ - ntor_during_tap_usec = estimated_usec_for_onionskins( - MIN(ol_entries[ONION_HANDSHAKE_TYPE_NTOR], - ol_entries[ONION_HANDSHAKE_TYPE_TAP] * get_num_ntors_per_tap()), - ONION_HANDSHAKE_TYPE_NTOR) / num_cpus; - /* See whether that exceeds MaxOnionQueueDelay. If so, we can't queue * this. */ if (type == ONION_HANDSHAKE_TYPE_NTOR && - (ntor_usec + tap_during_ntor_usec) / 1000 > max_onion_queue_delay) - return 0; - - if (type == ONION_HANDSHAKE_TYPE_TAP && - (tap_usec + ntor_during_tap_usec) / 1000 > max_onion_queue_delay) - return 0; - - /* If we support the ntor handshake, then don't let TAP handshakes use - * more than 2/3 of the space on the queue. */ - if (type == ONION_HANDSHAKE_TYPE_TAP && - tap_usec / 1000 > max_onion_queue_delay * 2 / 3) + (ntor_usec / 1000) > max_onion_queue_delay) return 0; return 1; @@ -292,38 +255,7 @@ static uint16_t decide_next_handshake_type(void) { - /* The number of times we've chosen ntor lately when both were available. */ - static int recently_chosen_ntors = 0; - - if (!ol_entries[ONION_HANDSHAKE_TYPE_NTOR]) - return ONION_HANDSHAKE_TYPE_TAP; /* no ntors? try tap */ - - if (!ol_entries[ONION_HANDSHAKE_TYPE_TAP]) { - - /* Nick wants us to prioritize new tap requests when there aren't - * any in the queue and we've processed k ntor cells since the last - * tap cell. This strategy is maybe a good idea, since it starves tap - * less in the case where tap is rare, or maybe a poor idea, since it - * makes the new tap cell unfairly jump in front of ntor cells that - * got here first. In any case this edge case will only become relevant - * once tap is rare. We should reevaluate whether we like this decision - * once tap gets more rare. */ - if (ol_entries[ONION_HANDSHAKE_TYPE_NTOR] && - recently_chosen_ntors <= get_num_ntors_per_tap()) - ++recently_chosen_ntors; - - return ONION_HANDSHAKE_TYPE_NTOR; /* no taps? try ntor */ - } - - /* They both have something queued. Pick ntor if we haven't done that - * too much lately. */ - if (++recently_chosen_ntors <= get_num_ntors_per_tap()) { - return ONION_HANDSHAKE_TYPE_NTOR; - } - - /* Else, it's time to let tap have its turn. */ - recently_chosen_ntors = 0; - return ONION_HANDSHAKE_TYPE_TAP; + return ONION_HANDSHAKE_TYPE_NTOR; } /** Remove the highest priority item from ol_list[] and return it, or @@ -445,10 +377,4 @@ ONION_QUEUE_WAIT_CUTOFF_DEFAULT, ONION_QUEUE_WAIT_CUTOFF_MIN, ONION_QUEUE_WAIT_CUTOFF_MAX); - - ns_num_ntors_per_tap = - networkstatus_get_param(ns, "NumNTorsPerTAP", - NUM_NTORS_PER_TAP_DEFAULT, - NUM_NTORS_PER_TAP_MIN, - NUM_NTORS_PER_TAP_MAX); } diff -Nru tor-0.4.8.16/src/feature/relay/relay_config.c tor-0.4.9.6/src/feature/relay/relay_config.c --- tor-0.4.8.16/src/feature/relay/relay_config.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/relay_config.c 2026-03-25 14:30:34.000000000 +0000 @@ -21,6 +21,7 @@ #include "lib/meminfo/meminfo.h" #include "lib/osinfo/uname.h" #include "lib/process/setuid.h" +#include "lib/crypt_ops/crypto_format.h" /* Required for dirinfo_type_t in or_options_t */ #include "core/or/or.h" @@ -693,7 +694,7 @@ * - "any" * - "https" * - "email" - * - "moat" + * - "settings" * * If the option string is unrecognised, a warning will be logged and 0 is * returned. If the option string contains an invalid character, -1 is @@ -706,7 +707,7 @@ return 0; const char *RECOGNIZED[] = { - "none", "any", "https", "email", "moat" + "none", "any", "https", "email", "settings" }; unsigned i; for (i = 0; i < ARRAY_LENGTH(RECOGNIZED); ++i) { @@ -1151,8 +1152,8 @@ REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid " "combination."); - if (options->BridgeRelay == 1 && (options->ExitRelay == 1 || - !policy_using_default_exit_options(options))) { + if (options->BridgeRelay == 1 && !(options->ExitRelay == 0 || + policy_using_default_exit_options(options))) { log_warn(LD_CONFIG, "BridgeRelay is 1, but ExitRelay is 1 or an " "ExitPolicy is configured. Tor will start, but it will not " "function as an exit relay."); @@ -1180,6 +1181,24 @@ options->MyFamily_lines, "MyFamily", msg)) return -1; + if (options->FamilyId_lines) { + options->FamilyIds = smartlist_new(); + config_line_t *line; + for (line = options->FamilyId_lines; line; line = line->next) { + if (!strcmp(line->value, "*")) { + options->AllFamilyIdsExpected = true; + continue; + } + + ed25519_public_key_t pk; + if (ed25519_public_from_base64(&pk, line->value) < 0) { + tor_asprintf(msg, "Invalid FamilyId %s", line->value); + return -1; + } + smartlist_add(options->FamilyIds, tor_memdup(&pk, sizeof(pk))); + } + } + if (options->ConstrainedSockets) { if (options->DirPort_set) { /* Providing cached directory entries while system TCP buffers are scarce @@ -1274,6 +1293,7 @@ YES_IF_CHANGED_STRING(ContactInfo); YES_IF_CHANGED_STRING(BridgeDistribution); YES_IF_CHANGED_LINELIST(MyFamily); + YES_IF_CHANGED_LINELIST(FamilyId_lines); YES_IF_CHANGED_STRING(AccountingStart); YES_IF_CHANGED_INT(AccountingMax); YES_IF_CHANGED_INT(AccountingRule); diff -Nru tor-0.4.8.16/src/feature/relay/relay_handshake.c tor-0.4.9.6/src/feature/relay/relay_handshake.c --- tor-0.4.8.16/src/feature/relay/relay_handshake.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/relay_handshake.c 2026-03-25 14:30:34.000000000 +0000 @@ -183,27 +183,17 @@ return 0; } -#ifdef TOR_UNIT_TESTS -int testing__connection_or_pretend_TLSSECRET_is_supported = 0; -#else -#define testing__connection_or_pretend_TLSSECRET_is_supported 0 -#endif - /** Return true iff challenge_type is an AUTHCHALLENGE type that * we can send and receive. */ int authchallenge_type_is_supported(uint16_t challenge_type) { switch (challenge_type) { - case AUTHTYPE_RSA_SHA256_TLSSECRET: -#ifdef HAVE_WORKING_TOR_TLS_GET_TLSSECRETS - return 1; -#else - return testing__connection_or_pretend_TLSSECRET_is_supported; -#endif case AUTHTYPE_ED25519_SHA256_RFC5705: return 1; - case AUTHTYPE_RSA_SHA256_RFC5705: + + case AUTHTYPE_RSA_SHA256_TLSSECRET: // obsolete. + case AUTHTYPE_RSA_SHA256_RFC5705: // never implemented. default: return 0; } @@ -243,11 +233,6 @@ tor_assert(sizeof(ac->challenge) == 32); crypto_rand((char*)ac->challenge, sizeof(ac->challenge)); - if (authchallenge_type_is_supported(AUTHTYPE_RSA_SHA256_TLSSECRET)) - auth_challenge_cell_add_methods(ac, AUTHTYPE_RSA_SHA256_TLSSECRET); - /* Disabled, because everything that supports this method also supports - * the much-superior ED25519_SHA256_RFC5705 */ - /* auth_challenge_cell_add_methods(ac, AUTHTYPE_RSA_SHA256_RFC5705); */ if (authchallenge_type_is_supported(AUTHTYPE_ED25519_SHA256_RFC5705)) auth_challenge_cell_add_methods(ac, AUTHTYPE_ED25519_SHA256_RFC5705); auth_challenge_cell_set_n_methods(ac, @@ -283,42 +268,36 @@ * determined by the rest of the handshake, and which match the provided value * exactly. * - * If server is false and signing_key is NULL, calculate the + * If server is false and ed_signing_key is NULL, calculate the * first V3_AUTH_BODY_LEN bytes of the authenticator (that is, everything * that should be signed), but don't actually sign it. * - * If server is false and signing_key is provided, calculate the - * entire authenticator, signed with signing_key. + * If server is false and ed_signing_key is provided, + * calculate the + * entire authenticator, signed with ed_signing_key. * * Return the length of the cell body on success, and -1 on failure. */ var_cell_t * connection_or_compute_authenticate_cell_body(or_connection_t *conn, const int authtype, - crypto_pk_t *signing_key, const ed25519_keypair_t *ed_signing_key, int server) { auth1_t *auth = NULL; - auth_ctx_t *ctx = auth_ctx_new(); var_cell_t *result = NULL; - int old_tlssecrets_algorithm = 0; const char *authtype_str = NULL; - int is_ed = 0; - /* assert state is reasonable XXXX */ switch (authtype) { case AUTHTYPE_RSA_SHA256_TLSSECRET: - authtype_str = "AUTH0001"; - old_tlssecrets_algorithm = 1; - break; case AUTHTYPE_RSA_SHA256_RFC5705: - authtype_str = "AUTH0002"; + /* These are unsupported; we should never reach this point. */ + tor_assert_nonfatal_unreached_once(); + return NULL; break; case AUTHTYPE_ED25519_SHA256_RFC5705: authtype_str = "AUTH0003"; - is_ed = 1; break; default: tor_assert(0); @@ -326,7 +305,6 @@ } auth = auth1_new(); - ctx->is_ed = is_ed; /* Type: 8 bytes. */ memcpy(auth1_getarray_type(auth), authtype_str, 8); @@ -355,7 +333,7 @@ memcpy(auth->sid, server_id, 32); } - if (is_ed) { + { const ed25519_public_key_t *my_ed_id, *their_ed_id; if (!conn->handshake_state->certs->ed_id_sign) { log_warn(LD_OR, "Ed authenticate without Ed ID cert from peer."); @@ -367,8 +345,8 @@ const uint8_t *cid_ed = (server ? their_ed_id : my_ed_id)->pubkey; const uint8_t *sid_ed = (server ? my_ed_id : their_ed_id)->pubkey; - memcpy(auth->u1_cid_ed, cid_ed, ED25519_PUBKEY_LEN); - memcpy(auth->u1_sid_ed, sid_ed, ED25519_PUBKEY_LEN); + memcpy(auth->cid_ed, cid_ed, ED25519_PUBKEY_LEN); + memcpy(auth->sid_ed, sid_ed, ED25519_PUBKEY_LEN); } { @@ -408,15 +386,8 @@ tor_x509_cert_free(cert); } - /* HMAC of clientrandom and serverrandom using master key : 32 octets */ - if (old_tlssecrets_algorithm) { - if (tor_tls_get_tlssecrets(conn->tls, auth->tlssecrets) < 0) { - log_fn(LOG_PROTOCOL_WARN, LD_OR, "Somebody asked us for an older TLS " - "authentication method (AUTHTYPE_RSA_SHA256_TLSSECRET) " - "which we don't support."); - goto err; - } - } else { + /* RFC5709 key exporter material : 32 octets */ + { char label[128]; tor_snprintf(label, sizeof(label), "EXPORTER FOR TOR TLS CLIENT BINDING %s", authtype_str); @@ -436,11 +407,9 @@ * checks it. That's followed by 16 bytes of nonce. */ crypto_rand((char*)auth->rand, 24); - ssize_t maxlen = auth1_encoded_len(auth, ctx); - if (ed_signing_key && is_ed) { + ssize_t maxlen = auth1_encoded_len(auth); + if (ed_signing_key) { maxlen += ED25519_SIG_LEN; - } else if (signing_key && !is_ed) { - maxlen += crypto_pk_keysize(signing_key); } const int AUTH_CELL_HEADER_LEN = 4; /* 2 bytes of type, 2 bytes of length */ @@ -452,7 +421,7 @@ result->command = CELL_AUTHENTICATE; set_uint16(result->payload, htons(authtype)); - if ((len = auth1_encode(out, outlen, auth, ctx)) < 0) { + if ((len = auth1_encode(out, outlen, auth)) < 0) { /* LCOV_EXCL_START */ log_warn(LD_BUG, "Unable to encode signed part of AUTH1 data."); goto err; @@ -461,7 +430,7 @@ if (server) { auth1_t *tmp = NULL; - ssize_t len2 = auth1_parse(&tmp, out, len, ctx); + ssize_t len2 = auth1_parse(&tmp, out, len); if (!tmp) { /* LCOV_EXCL_START */ log_warn(LD_BUG, "Unable to parse signed part of AUTH1 data that " @@ -481,7 +450,7 @@ goto done; } - if (ed_signing_key && is_ed) { + if (ed_signing_key) { ed25519_signature_t sig; if (ed25519_sign(&sig, out, len, ed_signing_key) < 0) { /* LCOV_EXCL_START */ @@ -491,25 +460,9 @@ } auth1_setlen_sig(auth, ED25519_SIG_LEN); memcpy(auth1_getarray_sig(auth), sig.sig, ED25519_SIG_LEN); - - } else if (signing_key && !is_ed) { - auth1_setlen_sig(auth, crypto_pk_keysize(signing_key)); - - char d[32]; - crypto_digest256(d, (char*)out, len, DIGEST_SHA256); - int siglen = crypto_pk_private_sign(signing_key, - (char*)auth1_getarray_sig(auth), - auth1_getlen_sig(auth), - d, 32); - if (siglen < 0) { - log_warn(LD_OR, "Unable to sign AUTH1 data."); - goto err; - } - - auth1_setlen_sig(auth, siglen); } - len = auth1_encode(out, outlen, auth, ctx); + len = auth1_encode(out, outlen, auth); if (len < 0) { /* LCOV_EXCL_START */ log_warn(LD_BUG, "Unable to encode signed AUTH1 data."); @@ -527,7 +480,6 @@ result = NULL; done: auth1_free(auth); - auth_ctx_free(ctx); return result; } @@ -537,13 +489,8 @@ connection_or_send_authenticate_cell,(or_connection_t *conn, int authtype)) { var_cell_t *cell; - crypto_pk_t *pk = tor_tls_get_my_client_auth_key(); /* XXXX make sure we're actually supposed to send this! */ - if (!pk) { - log_warn(LD_BUG, "Can't compute authenticate cell: no client auth key"); - return -1; - } if (! authchallenge_type_is_supported(authtype)) { log_warn(LD_BUG, "Tried to send authenticate cell with unknown " "authentication type %d", authtype); @@ -552,7 +499,6 @@ cell = connection_or_compute_authenticate_cell_body(conn, authtype, - pk, get_current_auth_keypair(), 0 /* not server */); if (! cell) { diff -Nru tor-0.4.8.16/src/feature/relay/relay_handshake.h tor-0.4.9.6/src/feature/relay/relay_handshake.h --- tor-0.4.8.16/src/feature/relay/relay_handshake.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/relay_handshake.h 2026-03-25 14:30:34.000000000 +0000 @@ -21,7 +21,6 @@ var_cell_t *connection_or_compute_authenticate_cell_body( or_connection_t *conn, const int authtype, - crypto_pk_t *signing_key, const struct ed25519_keypair_t *ed_signing_key, int server); @@ -56,13 +55,11 @@ connection_or_compute_authenticate_cell_body( or_connection_t *conn, const int authtype, - crypto_pk_t *signing_key, const struct ed25519_keypair_t *ed_signing_key, int server) { (void)conn; (void)authtype; - (void)signing_key; (void)ed_signing_key; (void)server; tor_assert_nonfatal_unreached(); diff -Nru tor-0.4.8.16/src/feature/relay/relay_metrics.c tor-0.4.9.6/src/feature/relay/relay_metrics.c --- tor-0.4.8.16/src/feature/relay/relay_metrics.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/relay_metrics.c 2026-03-25 14:30:34.000000000 +0000 @@ -13,6 +13,7 @@ #include "core/or/or.h" #include "core/mainloop/connection.h" #include "core/mainloop/mainloop.h" +#include "core/or/command.h" #include "core/or/congestion_control_common.h" #include "core/or/congestion_control_vegas.h" #include "core/or/congestion_control_flow.h" @@ -54,6 +55,9 @@ static void fill_onionskins_values(void); static void fill_oom_values(void); static void fill_streams_values(void); +static void fill_relay_circ_proto_violation(void); +static void fill_relay_destroy_cell(void); +static void fill_relay_drop_cell(void); static void fill_relay_flags(void); static void fill_tcp_exhaustion_values(void); static void fill_traffic_values(void); @@ -217,6 +221,27 @@ .help = "Total number of REND1 cells we received", .fill_fn = fill_rend1_cells, }, + { + .key = RELAY_METRICS_CIRC_DESTROY_CELL, + .type = METRICS_TYPE_COUNTER, + .name = METRICS_NAME(relay_destroy_cell_total), + .help = "Total number of DESTROY cell we received", + .fill_fn = fill_relay_destroy_cell, + }, + { + .key = RELAY_METRICS_CIRC_PROTO_VIOLATION, + .type = METRICS_TYPE_COUNTER, + .name = METRICS_NAME(relay_circ_proto_violation_total), + .help = "Total number of circuit protocol violation", + .fill_fn = fill_relay_circ_proto_violation, + }, + { + .key = RELAY_METRICS_CIRC_DROP_CELL, + .type = METRICS_TYPE_COUNTER, + .name = METRICS_NAME(relay_drop_cell_total), + .help = "Total number of DROP cell we received", + .fill_fn = fill_relay_drop_cell, + }, }; static const size_t num_base_metrics = ARRAY_LENGTH(base_metrics); @@ -433,6 +458,12 @@ metrics_store_entry_add_label(sentry, metrics_format_label("type", "introduce2_rejected")); metrics_store_entry_update(sentry, hs_dos_get_intro2_rejected_count()); + + sentry = metrics_store_add(the_store, rentry->type, rentry->name, + rentry->help, 0, NULL); + metrics_store_entry_add_label(sentry, + metrics_format_label("type", "stream_rejected")); + metrics_store_entry_update(sentry, dos_get_num_stream_rejected()); } /** Fill function for the RELAY_METRICS_CC_COUNTERS metric. */ @@ -1200,6 +1231,46 @@ } } +/** Fill the metrics store for the RELAY_METRICS_CIRC_DESTROY_CELL counter. */ +static void +fill_relay_destroy_cell(void) +{ + metrics_store_entry_t *sentry; + const relay_metrics_entry_t *rentry = + &base_metrics[RELAY_METRICS_CIRC_DESTROY_CELL]; + + sentry = metrics_store_add(the_store, rentry->type, rentry->name, + rentry->help, 0, NULL); + metrics_store_entry_update(sentry, + (int64_t) stats_n_destroy_cells_processed); +} + +/** Fill the metrics store for the RELAY_METRICS_CIRC_DROP_CELL counter. */ +static void +fill_relay_drop_cell(void) +{ + metrics_store_entry_t *sentry; + const relay_metrics_entry_t *rentry = + &base_metrics[RELAY_METRICS_CIRC_DROP_CELL]; + + sentry = metrics_store_add(the_store, rentry->type, rentry->name, + rentry->help, 0, NULL); + metrics_store_entry_update(sentry, rep_hist_get_drop_cell_received_count()); +} + +/** Fill the metrics store for the RELAY_METRICS_CIRC_PROTO_VIOLATION. */ +static void +fill_relay_circ_proto_violation(void) +{ + metrics_store_entry_t *sentry; + const relay_metrics_entry_t *rentry = + &base_metrics[RELAY_METRICS_CIRC_PROTO_VIOLATION]; + + sentry = metrics_store_add(the_store, rentry->type, rentry->name, + rentry->help, 0, NULL); + metrics_store_entry_update(sentry, circ_n_proto_violation); +} + /** Reset the global store and fill it with all the metrics from base_metrics * and their associated values. * diff -Nru tor-0.4.8.16/src/feature/relay/relay_metrics.h tor-0.4.9.6/src/feature/relay/relay_metrics.h --- tor-0.4.8.16/src/feature/relay/relay_metrics.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/relay_metrics.h 2026-03-25 14:30:34.000000000 +0000 @@ -57,6 +57,12 @@ RELAY_METRICS_NUM_INTRO1_CELLS, /** Number of times we received a REND1 cell */ RELAY_METRICS_NUM_REND1_CELLS, + /** Number of circuit closed by receiving a DESTROY cell. */ + RELAY_METRICS_CIRC_DESTROY_CELL, + /** Number of circuits closed due to protocol violation. */ + RELAY_METRICS_CIRC_PROTO_VIOLATION, + /** Number of drop cell seen. */ + RELAY_METRICS_CIRC_DROP_CELL, } relay_metrics_key_t; /** The metadata of a relay metric. */ diff -Nru tor-0.4.8.16/src/feature/relay/relay_periodic.c tor-0.4.9.6/src/feature/relay/relay_periodic.c --- tor-0.4.8.16/src/feature/relay/relay_periodic.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/relay_periodic.c 2026-03-25 14:30:34.000000000 +0000 @@ -241,7 +241,7 @@ log_warn(LD_CONFIG, "Your server has not managed to confirm reachability for " "its ORPort(s) at %s%s%s. Relays do not publish " - "descriptors until their ORPort and DirPort are " + "descriptors until their ORPort(s) are " "reachable. Please check your firewalls, ports, address, " "/etc/hosts file, etc.", where4?where4:"", diff -Nru tor-0.4.8.16/src/feature/relay/router.c tor-0.4.9.6/src/feature/relay/router.c --- tor-0.4.8.16/src/feature/relay/router.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/router.c 2026-03-25 14:30:34.000000000 +0000 @@ -211,8 +211,13 @@ mark_my_descriptor_dirty("set onion key"); } -/** Return the current onion key. Requires that the onion key has been - * loaded or generated. */ +/** Return the current TAP onion key. Requires that the onion key has been + * loaded or generated. + * + * Note that this key is no longer used for anything; we only keep it around + * because (as of June 2024) other Tor instances all expect to find it in + * our routerdescs. + **/ MOCK_IMPL(crypto_pk_t *, get_onion_key,(void)) { @@ -220,6 +225,25 @@ return onionkey; } +/** + * Return true iff we should include our TAP onion key in our router + * descriptor. + */ +static int +should_publish_tap_onion_key(void) +{ +#define SHOULD_PUBLISH_TAP_MIN 0 +#define SHOULD_PUBLISH_TAP_MAX 1 + /* Note that we err on the side of publishing. */ +#define SHOULD_PUBLISH_TAP_DFLT 1 + + return networkstatus_get_param(NULL, + "publish-dummy-tap-key", + SHOULD_PUBLISH_TAP_DFLT, + SHOULD_PUBLISH_TAP_MIN, + SHOULD_PUBLISH_TAP_MAX); +} + /** Store a full copy of the current onion key into *key, and a full * copy of the most recent onion key into *last. Store NULL into * a pointer if the corresponding key does not exist. @@ -358,6 +382,7 @@ log_err(LD_BUG, "Couldn't compute our own identity key digest."); tor_assert(0); } + pt_update_bridge_lines(); } #ifdef TOR_UNIT_TESTS @@ -852,6 +877,7 @@ STATIC void router_announce_bridge_status_page(void) { +#ifdef ENABLE_MODULE_RELAY char fingerprint[FINGERPRINT_LEN + 1]; if (crypto_pk_get_hashed_fingerprint(get_server_identity_key(), @@ -865,6 +891,7 @@ log_notice(LD_GENERAL, "You can check the status of your bridge relay at " "https://bridges.torproject.org/status?id=%s", fingerprint); +#endif } /** Compute fingerprint (or hashed fingerprint if hashed is 1) and write @@ -1041,6 +1068,11 @@ if (new_signing_key < 0) return -1; + if (options->command == CMD_RUN_TOR) { + if (load_family_id_keys(options, networkstatus_get_latest_consensus()) < 0) + return -1; + } + /* 2. Read onion key. Make it if none is found. */ keydir = get_keydir_fname("secret_onion_key"); log_info(LD_GENERAL,"Reading/making onion key \"%s\"...",keydir); @@ -1254,13 +1286,12 @@ /** Helper: Return 1 if we have sufficient resources for serving directory * requests, return 0 otherwise. - * dir_port is either 0 or the configured DirPort number. * If AccountingMax is set less than our advertised bandwidth, then don't * serve requests. Likewise, if our advertised bandwidth is less than * MIN_BW_TO_ADVERTISE_DIRSERVER, don't bother trying to serve requests. */ static int -router_should_be_dirserver(const or_options_t *options, int dir_port) +router_should_be_dirserver(const or_options_t *options) { static int advertising=1; /* start out assuming we will advertise */ int new_choice=1; @@ -1269,7 +1300,8 @@ if (accounting_is_enabled(options) && get_options()->AccountingRule != ACCT_IN) { /* Don't spend bytes for directory traffic if we could end up hibernating, - * but allow DirPort otherwise. Some relay operators set AccountingMax + * but allow being a dir cache otherwise. + * Some relay operators set AccountingMax * because they're confused or to get statistics. Directory traffic has a * much larger effect on output than input so there is no reason to turn it * off if using AccountingRule in. */ @@ -1281,10 +1313,9 @@ "seconds long. Raising to 1."); interval_length = 1; } - log_info(LD_GENERAL, "Calculating whether to advertise %s: effective " - "bwrate: %u, AccountingMax: %"PRIu64", " + log_info(LD_GENERAL, "Calculating whether to advertise begindir: " + "effective bwrate: %u, AccountingMax: %"PRIu64", " "accounting interval length %d", - dir_port ? "dirport" : "begindir", effective_bw, (options->AccountingMax), interval_length); @@ -1304,14 +1335,11 @@ if (advertising != new_choice) { if (new_choice == 1) { - if (dir_port > 0) - log_notice(LD_DIR, "Advertising DirPort as %d", dir_port); - else - log_notice(LD_DIR, "Advertising directory service support"); + log_notice(LD_DIR, "Advertising directory service support"); } else { tor_assert(reason); - log_notice(LD_DIR, "Not advertising Dir%s (Reason: %s)", - dir_port ? "Port" : "ectory Service support", reason); + log_notice(LD_DIR, "Not advertising Directory Service support " + "(Reason: %s)", reason); } advertising = new_choice; } @@ -1320,17 +1348,13 @@ } /** Look at a variety of factors, and return 0 if we don't want to - * advertise the fact that we have a DirPort open or begindir support, else + * advertise the fact that we have begindir support, else * return 1. * - * Where dir_port or supports_tunnelled_dir_requests are not relevant, they - * must be 0. - * * Log a helpful message if we change our mind about whether to publish. */ static int decide_to_advertise_dir_impl(const or_options_t *options, - uint16_t dir_port, int supports_tunnelled_dir_requests) { /* Part one: reasons to publish or not publish that aren't @@ -1338,24 +1362,21 @@ * or because they're normal behavior. */ /* short circuit the rest of the function */ - if (!dir_port && !supports_tunnelled_dir_requests) + if (!supports_tunnelled_dir_requests) return 0; if (authdir_mode(options)) /* always publish */ return 1; if (net_is_disabled()) return 0; - if (dir_port && !routerconf_find_dir_port(options, dir_port)) - return 0; - if (supports_tunnelled_dir_requests && - !routerconf_find_or_port(options, AF_INET)) + if (!routerconf_find_or_port(options, AF_INET)) return 0; /* Part two: consider config options that could make us choose to * publish or not publish that the user might find surprising. */ - return router_should_be_dirserver(options, dir_port); + return router_should_be_dirserver(options); } -/** Front-end to decide_to_advertise_dir_impl(): return 0 if we don't want to +/** Return 0 if we don't want to * advertise the fact that we have a DirPort open, else return the * DirPort we want to advertise. */ @@ -1373,8 +1394,7 @@ router_should_advertise_begindir(const or_options_t *options, int supports_tunnelled_dir_requests) { - /* dir_port is not relevant, pass 0 */ - return decide_to_advertise_dir_impl(options, 0, + return decide_to_advertise_dir_impl(options, supports_tunnelled_dir_requests); } @@ -1403,17 +1423,14 @@ static bool publish_even_when_ipv6_orport_unreachable = false; /** Decide if we're a publishable server. We are a publishable server if: + * - We are an authoritative directory server, or if * - We don't have the ClientOnly option set * and * - We have the PublishServerDescriptor option set to non-empty * and * - We have ORPort set * and - * - We believe our ORPort and DirPort (if present) are reachable from - * the outside; or - * - We believe our ORPort is reachable from the outside, and we can't - * check our DirPort because the consensus has no exits; or - * - We are an authoritative directory server. + * - We believe our ORPort is reachable from the outside. */ static int decide_if_publishable_server(void) @@ -1446,13 +1463,7 @@ return 0; } } - if (router_have_consensus_path() == CONSENSUS_PATH_INTERNAL) { - /* All set: there are no exits in the consensus (maybe this is a tiny - * test network), so we can't check our DirPort reachability. */ - return 1; - } else { - return router_dirport_seems_reachable(options); - } + return 1; /* everything looks good! publish. */ } /** Initiate server descriptor upload as reasonable (if server is publishable, @@ -2138,9 +2149,12 @@ ri->supports_tunnelled_dir_requests = directory_permits_begindir_requests(options); ri->cache_info.published_on = time(NULL); - /* get_onion_key() must invoke from main thread */ - router_set_rsa_onion_pkey(get_onion_key(), &ri->onion_pkey, - &ri->onion_pkey_len); + + if (should_publish_tap_onion_key()) { + /* get_onion_key() must invoke from main thread */ + router_set_rsa_onion_pkey(get_onion_key(), &ri->tap_onion_pkey, + &ri->tap_onion_pkey_len); + } ri->onion_curve25519_pkey = tor_memdup(&get_current_curve25519_keypair()->pubkey, @@ -2501,6 +2515,21 @@ publish_even_when_ipv4_orport_unreachable = ar; publish_even_when_ipv6_orport_unreachable = ar || ar6; + + warn_about_family_id_config(get_options(), ns); +} + +/** + * Return true if the parameters in `ns` say that we should publish + * a legacy family list. + * + * Use the latest networkstatus (or returns the default) if `ns` is NULL. + */ +bool +should_publish_family_list(const networkstatus_t *ns) +{ + return networkstatus_get_param(ns, "publish-family-list", + 1, 0, 1); // default, min, max } /** Mark our descriptor out of data iff the IPv6 omit status flag is flipped @@ -2777,7 +2806,7 @@ char published[ISO_TIME_LEN+1]; char fingerprint[FINGERPRINT_LEN+1]; char *extra_info_line = NULL; - size_t onion_pkeylen, identity_pkeylen; + size_t onion_pkeylen=0, identity_pkeylen; char *family_line = NULL; char *extra_or_address = NULL; const or_options_t *options = get_options(); @@ -2835,12 +2864,14 @@ } /* PEM-encode the onion key */ - rsa_pubkey = router_get_rsa_onion_pkey(router->onion_pkey, - router->onion_pkey_len); - if (crypto_pk_write_public_key_to_string(rsa_pubkey, - &onion_pkey,&onion_pkeylen)<0) { - log_warn(LD_BUG,"write onion_pkey to string failed!"); - goto err; + rsa_pubkey = router_get_rsa_onion_pkey(router->tap_onion_pkey, + router->tap_onion_pkey_len); + if (rsa_pubkey) { + if (crypto_pk_write_public_key_to_string(rsa_pubkey, + &onion_pkey,&onion_pkeylen)<0) { + log_warn(LD_BUG,"write onion_pkey to string failed!"); + goto err; + } } /* PEM-encode the identity key */ @@ -2851,7 +2882,7 @@ } /* Cross-certify with RSA key */ - if (tap_key && router->cache_info.signing_key_cert && + if (tap_key && rsa_pubkey && router->cache_info.signing_key_cert && router->cache_info.signing_key_cert->signing_key_included) { char buf[256]; int tap_cc_len = 0; @@ -2976,7 +3007,7 @@ "uptime %ld\n" "bandwidth %d %d %d\n" "%s%s" - "onion-key\n%s" + "%s%s" "signing-key\n%s" "%s%s" "%s%s%s", @@ -2997,13 +3028,43 @@ extra_info_line ? extra_info_line : "", (options->DownloadExtraInfo || options->V3AuthoritativeDir) ? "caches-extra-info\n" : "", - onion_pkey, identity_pkey, + onion_pkey?"onion-key\n":"", onion_pkey?onion_pkey:"", + identity_pkey, rsa_tap_cc_line ? rsa_tap_cc_line : "", ntor_cc_line ? ntor_cc_line : "", family_line, we_are_hibernating() ? "hibernating 1\n" : "", "hidden-service-dir\n"); + SMARTLIST_FOREACH_BEGIN(get_current_family_id_keys(), + const ed25519_keypair_t *, k_family_id) { + // TODO PROP321: We may want this to be configurable; + // we can probably use a smaller value. +#define FAMILY_CERT_LIFETIME (30*86400) + tor_cert_t *family_cert = tor_cert_create_ed25519( + k_family_id, + CERT_TYPE_FAMILY_V_IDENTITY, + // (this is the identity key "KP_relayid_ed") + &router->cache_info.signing_key_cert->signing_key, + router->cache_info.published_on, + FAMILY_CERT_LIFETIME, CERT_FLAG_INCLUDE_SIGNING_KEY); + char family_cert_base64[256]; + if (base64_encode(family_cert_base64, sizeof(family_cert_base64), + (const char*) family_cert->encoded, + family_cert->encoded_len, BASE64_ENCODE_MULTILINE) < 0) { + log_err(LD_BUG, "Base64 encoding family cert failed!?"); + tor_cert_free(family_cert); + goto err; + } + smartlist_add_asprintf(chunks, + "family-cert\n" + "-----BEGIN FAMILY CERT-----\n" + "%s" + "-----END FAMILY CERT-----\n", + family_cert_base64); + tor_cert_free(family_cert); + } SMARTLIST_FOREACH_END(k_family_id); + if (options->ContactInfo && strlen(options->ContactInfo)) { const char *ci = options->ContactInfo; if (strchr(ci, '\n') || strchr(ci, '\r')) diff -Nru tor-0.4.8.16/src/feature/relay/router.h tor-0.4.9.6/src/feature/relay/router.h --- tor-0.4.8.16/src/feature/relay/router.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/router.h 2026-03-25 14:30:34.000000000 +0000 @@ -81,6 +81,8 @@ int should_refuse_unknown_exits(const or_options_t *options); void router_new_consensus_params(const networkstatus_t *); +bool should_publish_family_list(const networkstatus_t *ns); + void router_upload_dir_desc_to_dirservers(int force); void mark_my_descriptor_dirty_if_too_old(time_t now); void mark_my_descriptor_dirty(const char *reason); diff -Nru tor-0.4.8.16/src/feature/relay/routerkeys.c tor-0.4.9.6/src/feature/relay/routerkeys.c --- tor-0.4.8.16/src/feature/relay/routerkeys.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/routerkeys.c 2026-03-25 14:30:34.000000000 +0000 @@ -14,6 +14,8 @@ * (TODO: The keys in router.c should go here too.) */ +#define ROUTERKEYS_PRIVATE + #include "core/or/or.h" #include "app/config/config.h" #include "feature/relay/router.h" @@ -21,8 +23,11 @@ #include "feature/relay/routermode.h" #include "feature/keymgt/loadkey.h" #include "feature/nodelist/torcert.h" +#include "feature/nodelist/networkstatus_st.h" +#include "feature/dirauth/dirvote.h" #include "lib/crypt_ops/crypto_util.h" +#include "lib/crypt_ops/crypto_format.h" #include "lib/tls/tortls.h" #include "lib/tls/x509.h" @@ -44,6 +49,9 @@ static size_t rsa_ed_crosscert_len = 0; static time_t rsa_ed_crosscert_expiration = 0; +// list of ed25519_keypair_t +static smartlist_t *family_id_keys = NULL; + /** * Running as a server: load, reload, or refresh our ed25519 keys and * certificates, creating and saving new ones as needed. @@ -674,6 +682,344 @@ return auth_key_cert; } +/** + * Suffix for the filenames in which we expect to find a family ID key. + */ +#define FAMILY_KEY_SUFFIX ".secret_family_key" + +/** + * Return true if `fname` is a possible filename of a family ID key. + * + * Family ID key filenames are FAMILY_KEY_FNAME, followed optionally + * by "." and a positive integer. + */ +STATIC bool +is_family_key_fname(const char *fname) +{ + return 0 == strcmpend(fname, FAMILY_KEY_SUFFIX); +} + +/** Return true if `id` is configured in `options`. */ +static bool +family_key_id_is_expected(const or_options_t *options, + const ed25519_public_key_t *id) +{ + if (options->AllFamilyIdsExpected) + return true; + + SMARTLIST_FOREACH(options->FamilyIds, const ed25519_public_key_t *, k, { + if (ed25519_pubkey_eq(k, id)) + return true; + }); + return false; +} + +/** Return true if the key for `id` has been loaded. */ +static bool +family_key_is_present(const ed25519_public_key_t *id) +{ + if (!family_id_keys) + return false; + + SMARTLIST_FOREACH(family_id_keys, const ed25519_keypair_t *, kp, { + if (ed25519_pubkey_eq(&kp->pubkey, id)) + return true; + }); + return false; +} + +/** + * Tag to use on family key files. + */ +#define FAMILY_KEY_FILE_TAG "fmly-id" + +/** Return a list of all the possible family-key files in `keydir`. + * Return NULL on error. + * + * (Unlike list_family_key_files, this function does not use a cached + * list when the seccomp2 sandbox is enabled.) */ +static smartlist_t * +list_family_key_files_impl(const char *keydir) +{ + smartlist_t *files = tor_listdir(keydir); + smartlist_t *result = smartlist_new(); + + if (!files) { + log_warn(LD_OR, "Unable to list contents of directory %s", keydir); + goto err; + } + + SMARTLIST_FOREACH_BEGIN(files, const char *, fn) { + if (!is_family_key_fname(fn)) + continue; + + smartlist_add_asprintf(result, "%s%s%s", keydir, PATH_SEPARATOR, fn); + } SMARTLIST_FOREACH_END(fn); + + goto done; + err: + SMARTLIST_FOREACH(result, char *, cp, tor_free(cp)); + smartlist_free(result); // sets result to NULL. + done: + if (files) { + SMARTLIST_FOREACH(files, char *, cp, tor_free(cp)); + smartlist_free(files); + } + + return result; +} + +/** + * A list of files returned by list_family_key_files_impl. + * Used when the seccomp2 sandbox is enabled. + */ +static smartlist_t *cached_family_key_file_list = NULL; + +/** Return a list of all the possible family-key files in `keydir`. + * Return NULL on error. + */ +smartlist_t * +list_family_key_files(const or_options_t *options, + const char *keydir) +{ + if (options->Sandbox) { + if (!cached_family_key_file_list) + cached_family_key_file_list = list_family_key_files_impl(keydir); + if (!cached_family_key_file_list) + return NULL; + + smartlist_t *result = smartlist_new(); + SMARTLIST_FOREACH(cached_family_key_file_list, char *, fn, + smartlist_add_strdup(result, fn)); + return result; + } + + return list_family_key_files_impl(keydir); +} + +/** + * Look for all the family keys in `keydir`, load them into + * family_id_keys. + */ +STATIC int +load_family_id_keys_impl(const or_options_t *options, + const char *keydir) +{ + if (BUG(!options) || BUG(!keydir)) + return -1; + + smartlist_t *key_files = list_family_key_files(options, keydir); + smartlist_t *new_keys = NULL; + ed25519_keypair_t *kp_tmp = NULL; + char *tag_tmp = NULL; + int r = -1; + + if (key_files == NULL) { + goto end; // already warned. + } + + new_keys = smartlist_new(); + SMARTLIST_FOREACH_BEGIN(key_files, const char *, fn) { + kp_tmp = tor_malloc_zero(sizeof(*kp_tmp)); + // TODO: If we ever allow cert provisioning here, + // use ed_key_init_from_file() instead. + if (ed25519_seckey_read_from_file(&kp_tmp->seckey, &tag_tmp, fn) < 0) { + log_warn(LD_OR, "%s was not an ed25519 secret key.", fn); + goto end; + } + if (0 != strcmp(tag_tmp, FAMILY_KEY_FILE_TAG)) { + log_warn(LD_OR, "%s was not a family ID key.", fn); + goto end; + } + if (ed25519_public_key_generate(&kp_tmp->pubkey, &kp_tmp->seckey) < 0) { + log_warn(LD_OR, "Unable to generate public key for %s", fn); + goto end; + } + + if (family_key_id_is_expected(options, &kp_tmp->pubkey)) { + smartlist_add(new_keys, kp_tmp); + kp_tmp = NULL; // prevent double-free + } else { + log_warn(LD_OR, "Found secret family key in %s " + "with unexpected FamilyID %s", + fn, ed25519_fmt(&kp_tmp->pubkey)); + } + + ed25519_keypair_free(kp_tmp); + tor_free(tag_tmp); + } SMARTLIST_FOREACH_END(fn); + + set_family_id_keys(new_keys); + new_keys = NULL; // prevent double-free + r = 0; + end: + if (key_files) { + SMARTLIST_FOREACH(key_files, char *, cp, tor_free(cp)); + smartlist_free(key_files); + } + if (new_keys) { + SMARTLIST_FOREACH(new_keys, ed25519_keypair_t *, kp, + ed25519_keypair_free(kp)); + smartlist_free(new_keys); + } + tor_free(tag_tmp); + ed25519_keypair_free(kp_tmp); + return r; +} + +/** + * Create a new family ID key, and store it in `fname`. + * + * If pk_out is provided, set it to the generated public key. + **/ +int +create_family_id_key(const char *fname, ed25519_public_key_t *pk_out) +{ + int r = -1; + ed25519_keypair_t *kp = tor_malloc_zero(sizeof(ed25519_keypair_t)); + + /* Refuse to overwrite an existing family key */ + if (file_status(fname) == FN_FILE) { + log_warn(LD_GENERAL, + "Family key file '%s' already exists. " + "Refusing to overwrite existing family key.", + fname); + goto done; + } + + if (ed25519_keypair_generate(kp, 1) < 0) { + log_warn(LD_BUG, "Can't generate ed25519 key!"); + goto done; + } + + if (ed25519_seckey_write_to_file(&kp->seckey, + fname, FAMILY_KEY_FILE_TAG)<0) { + log_warn(LD_BUG, "Can't write key to file."); + goto done; + } + + if (pk_out) { + ed25519_pubkey_copy(pk_out, &kp->pubkey); + } + + r = 0; + + done: + ed25519_keypair_free(kp); + return r; +} + +/** + * If configured to do so, load our family keys from the key directory. + * Otherwise, clear the family keys. + * + * Additionally, warn about inconsistencies between family options. + * If `ns` is provided, provide additional warnings. + * + * `options` is required; `ns` may be NULL. + */ +int +load_family_id_keys(const or_options_t *options, + const networkstatus_t *ns) +{ + if (options->FamilyIds) { + if (load_family_id_keys_impl(options, options->FamilyKeyDirectory) < 0) + return -1; + + bool any_missing = false; + SMARTLIST_FOREACH_BEGIN(options->FamilyIds, + const ed25519_public_key_t *, id) { + if (!family_key_is_present(id)) { + log_err(LD_OR, "No key was found for listed FamilyID %s", + ed25519_fmt(id)); + any_missing = true; + } + } SMARTLIST_FOREACH_END(id); + if (any_missing) + return -1; + + log_info(LD_OR, "Found %d family ID keys", + smartlist_len(get_current_family_id_keys())); + } else { + set_family_id_keys(NULL); + } + warn_about_family_id_config(options, ns); + return 0; +} + +#define FAMILY_INFO_URL \ + "https://community.torproject.org/relay/setup/post-install/family-ids/" + +/** Generate warnings as appropriate about our family ID configuration. + * + * `options` is required; `ns` may be NULL. + */ +void +warn_about_family_id_config(const or_options_t *options, + const networkstatus_t *ns) +{ + static int have_warned_absent_myfamily = 0; + static int have_warned_absent_familykeys = 0; + + if (options->FamilyIds) { + if (!have_warned_absent_myfamily && + !options->MyFamily && ns && should_publish_family_list(ns)) { + log_warn(LD_OR, + "FamilyId was configured, but MyFamily was not. " + "FamilyId is good, but the Tor network still requires " + "MyFamily while clients are migrating to use family " + "keys instead."); + have_warned_absent_myfamily = 1; + } + } else { + if (!have_warned_absent_familykeys && + options->MyFamily && + ns && ns->consensus_method >= MIN_METHOD_FOR_FAMILY_IDS) { + log_notice(LD_OR, + "MyFamily was configured, but FamilyId was not. " + "It's a good time to start migrating your relays " + "to use family keys. " + "See "FAMILY_INFO_URL " for instructions."); + have_warned_absent_familykeys = 1; + } + } +} + +/** + * Return a list of our current family id keypairs, + * as a list of `ed25519_keypair_t`. + * + * Never returns NULL. + * + * TODO PROP321: Right now this is only used in testing; + * when we add relay support we'll need a way to actually + * read these keys from disk. + **/ +const smartlist_t * +get_current_family_id_keys(void) +{ + if (family_id_keys == NULL) + family_id_keys = smartlist_new(); + return family_id_keys; +} + +/** + * Replace our list of family ID keys with `family_id_keys`, + * which must be a list of `ed25519_keypair_t`. + * + * Takes ownership of its input. + */ +STATIC void +set_family_id_keys(smartlist_t *keys) +{ + if (family_id_keys) { + SMARTLIST_FOREACH(family_id_keys, ed25519_keypair_t *, kp, + ed25519_keypair_free(kp)); + smartlist_free(family_id_keys); + } + family_id_keys = keys; +} + void get_master_rsa_crosscert(const uint8_t **cert_out, size_t *size_out) @@ -746,11 +1092,18 @@ ed25519_keypair_free(master_identity_key); ed25519_keypair_free(master_signing_key); ed25519_keypair_free(current_auth_key); + set_family_id_keys(NULL); + tor_cert_free(signing_key_cert); tor_cert_free(link_cert_cert); tor_cert_free(auth_key_cert); tor_free(rsa_ed_crosscert); + if (cached_family_key_file_list) { + SMARTLIST_FOREACH(cached_family_key_file_list, char *, cp, tor_free(cp)); + smartlist_free(cached_family_key_file_list); + } + master_identity_key = master_signing_key = NULL; current_auth_key = NULL; signing_key_cert = link_cert_cert = auth_key_cert = NULL; diff -Nru tor-0.4.8.16/src/feature/relay/routerkeys.h tor-0.4.9.6/src/feature/relay/routerkeys.h --- tor-0.4.8.16/src/feature/relay/routerkeys.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/routerkeys.h 2026-03-25 14:30:34.000000000 +0000 @@ -21,6 +21,10 @@ const struct tor_cert_st *get_current_link_cert_cert(void); const struct tor_cert_st *get_current_auth_key_cert(void); +smartlist_t *list_family_key_files(const or_options_t *options, + const char *keydir); +const smartlist_t *get_current_family_id_keys(void); + void get_master_rsa_crosscert(const uint8_t **cert_out, size_t *size_out); @@ -39,6 +43,11 @@ int log_cert_expiration(void); int load_ed_keys(const or_options_t *options, time_t now); +int load_family_id_keys(const or_options_t *options, + const networkstatus_t *ns); +int create_family_id_key(const char *fname, ed25519_public_key_t *pk_out); +void warn_about_family_id_config(const or_options_t *options, + const networkstatus_t *ns); int should_make_new_ed_keys(const or_options_t *options, const time_t now); int generate_ed_link_cert(const or_options_t *options, time_t now, int force); @@ -82,6 +91,10 @@ ((void)(options), (void)(now), (void)(force), 0) #define should_make_new_ed_keys(options, now) \ ((void)(options), (void)(now), 0) +#define warn_about_family_id_config(options,ns) \ + ((void)(options), (void)(ns)) +#define get_current_family_id_keys() \ + (smartlist_new()) // These can get removed once router.c becomes relay-only. static inline struct tor_cert_st * @@ -120,6 +133,10 @@ * CMD_KEYGEN. */ #define load_ed_keys(x,y) \ (puts("Not available: Tor has been compiled without relay support"), 0) +#define load_family_id_keys(x,y) \ + (puts("Not available: Tor has been compiled without relay support"), 0) +#define create_family_id_key(x,y) \ + (puts("Not available: Tor has been compiled without relay support"), -1) #endif /* defined(HAVE_MODULE_RELAY) */ @@ -128,4 +145,11 @@ void init_mock_ed_keys(const crypto_pk_t *rsa_identity_key); #endif +#ifdef ROUTERKEYS_PRIVATE +STATIC void set_family_id_keys(smartlist_t *keys); +STATIC bool is_family_key_fname(const char *fname); +STATIC int load_family_id_keys_impl(const or_options_t *options, + const char *keydir); +#endif + #endif /* !defined(TOR_ROUTERKEYS_H) */ diff -Nru tor-0.4.8.16/src/feature/relay/selftest.c tor-0.4.9.6/src/feature/relay/selftest.c --- tor-0.4.8.16/src/feature/relay/selftest.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/selftest.c 2026-03-25 14:30:34.000000000 +0000 @@ -130,16 +130,6 @@ return true; } -/** Relay DirPorts are no longer used (though authorities are). In either case, - * reachability self test is done anymore, since network re-entry towards an - * authority DirPort is not allowed. Thus, consider it always reachable. */ -int -router_dirport_seems_reachable(const or_options_t *options) -{ - (void) options; - return 1; -} - /** See if we currently believe our ORPort to be unreachable. If so, return 1 * else return 0. */ static int @@ -201,7 +191,6 @@ static extend_info_t * extend_info_from_router(const routerinfo_t *r, int family) { - crypto_pk_t *rsa_pubkey; extend_info_t *info; tor_addr_port_t ap; @@ -224,15 +213,14 @@ /* We don't have an ORPort for the requested family. */ return NULL; } - rsa_pubkey = router_get_rsa_onion_pkey(r->onion_pkey, r->onion_pkey_len); info = extend_info_new(r->nickname, r->cache_info.identity_digest, ed_id_key, - rsa_pubkey, r->onion_curve25519_pkey, + r->onion_curve25519_pkey, &ap.addr, ap.port, /* TODO-324: Should self-test circuits use * congestion control? */ NULL, false); - crypto_pk_free(rsa_pubkey); + return info; } diff -Nru tor-0.4.8.16/src/feature/relay/selftest.h tor-0.4.9.6/src/feature/relay/selftest.h --- tor-0.4.8.16/src/feature/relay/selftest.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/relay/selftest.h 2026-03-25 14:30:34.000000000 +0000 @@ -20,8 +20,6 @@ int router_orport_seems_reachable( const struct or_options_t *options, int family); -int router_dirport_seems_reachable( - const struct or_options_t *options); void router_do_reachability_checks(void); void router_perform_bandwidth_test(int num_circs, time_t now); diff -Nru tor-0.4.8.16/src/feature/rend/include.am tor-0.4.9.6/src/feature/rend/include.am --- tor-0.4.8.16/src/feature/rend/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/rend/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -5,6 +5,6 @@ src/feature/rend/rendmid.c # ADD_C_FILE: INSERT HEADERS HERE. -noinst_HEADERS += \ - src/feature/rend/rendcommon.h \ +noinst_HEADERS += \ + src/feature/rend/rendcommon.h \ src/feature/rend/rendmid.h diff -Nru tor-0.4.8.16/src/feature/stats/geoip_stats.c tor-0.4.9.6/src/feature/stats/geoip_stats.c --- tor-0.4.8.16/src/feature/stats/geoip_stats.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/stats/geoip_stats.c 2026-03-25 14:30:34.000000000 +0000 @@ -305,6 +305,7 @@ geoip_client_action_t action) { clientmap_entry_t lookup; + memset(&lookup, 0, sizeof(lookup)); tor_assert(addr); @@ -389,8 +390,8 @@ * statuses? */ static uint32_t ns_v3_responses[GEOIP_NS_RESPONSE_NUM]; -/** Note that we've rejected a client's request for a v3 network status - * for reason reason at time now. */ +/** Note how we have handled a client's request for a v3 network status: + * with reason at time now. */ void geoip_note_ns_response(geoip_ns_response_t response) { @@ -996,7 +997,8 @@ tor_asprintf(&result, "dirreq-stats-end %s (%d s)\n" "dirreq-v3-ips %s\n" "dirreq-v3-reqs %s\n" - "dirreq-v3-resp ok=%u,not-enough-sigs=%u,unavailable=%u," + "dirreq-v3-resp " + "served=%u,ok=%u,not-enough-sigs=%u,unavailable=%u," "not-found=%u,not-modified=%u,busy=%u\n" "dirreq-v3-direct-dl %s\n" "dirreq-v3-tunneled-dl %s\n", @@ -1004,6 +1006,7 @@ (unsigned) (now - start_of_dirreq_stats_interval), v3_ips_string ? v3_ips_string : "", v3_reqs_string ? v3_reqs_string : "", + ns_v3_responses[GEOIP_SERVED], ns_v3_responses[GEOIP_SUCCESS], ns_v3_responses[GEOIP_REJECT_NOT_ENOUGH_SIGS], ns_v3_responses[GEOIP_REJECT_UNAVAILABLE], diff -Nru tor-0.4.8.16/src/feature/stats/geoip_stats.h tor-0.4.9.6/src/feature/stats/geoip_stats.h --- tor-0.4.8.16/src/feature/stats/geoip_stats.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/stats/geoip_stats.h 2026-03-25 14:30:34.000000000 +0000 @@ -25,7 +25,7 @@ /** We've served a networkstatus consensus as a directory server. */ GEOIP_CLIENT_NETWORKSTATUS = 1, } geoip_client_action_t; -/** Indicates either a positive reply or a reason for rejectng a network +/** Indicates either a positive reply or a reason for rejecting a network * status request that will be included in geoip statistics. */ typedef enum { /** Request is answered successfully. */ @@ -41,8 +41,11 @@ GEOIP_REJECT_NOT_MODIFIED = 4, /** Directory is busy. */ GEOIP_REJECT_BUSY = 5, + /** We began to serve the request, and when we feel we have finished + * serving it we will note this with a GEOIP_SUCCESS call too. */ + GEOIP_SERVED = 6, } geoip_ns_response_t; -#define GEOIP_NS_RESPONSE_NUM 6 +#define GEOIP_NS_RESPONSE_NUM 7 /** Directory requests that we are measuring can be either direct or * tunneled. */ diff -Nru tor-0.4.8.16/src/feature/stats/include.am tor-0.4.9.6/src/feature/stats/include.am --- tor-0.4.8.16/src/feature/stats/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/stats/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -9,7 +9,7 @@ # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ - src/feature/stats/bw_array_st.h \ + src/feature/stats/bw_array_st.h \ src/feature/stats/bwhist.h \ src/feature/stats/connstats.h \ src/feature/stats/geoip_stats.h \ diff -Nru tor-0.4.8.16/src/feature/stats/rephist.c tor-0.4.9.6/src/feature/stats/rephist.c --- tor-0.4.8.16/src/feature/stats/rephist.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/stats/rephist.c 2026-03-25 14:30:34.000000000 +0000 @@ -280,6 +280,9 @@ /** DNS query statistics store. It covers all type of queries. */ static dns_stats_t dns_all_stats; +/** Counter of the total number of DROP cell received. */ +static uint64_t relay_circ_n_drop_cell_received = 0; + /** Return the point to the DNS statistics store. Ignore the type for now * because of a libevent problem. */ static inline dns_stats_t * @@ -2290,19 +2293,14 @@ /** Keep track of the onionskin requests for an assessment period. */ static overload_onionskin_assessment_t overload_onionskin_assessment; -/** - * We combine ntorv3 and ntor into the same stat, so we must - * use this function to convert the cell type to a stat index. +/** This function ensures that we clamp the maximum value of the given input + * type to NTOR in case the input is out of range. */ static inline uint16_t onionskin_type_to_stat(uint16_t type) { - if (type == ONION_HANDSHAKE_TYPE_NTOR_V3) { - return ONION_HANDSHAKE_TYPE_NTOR; - } - if (BUG(type > MAX_ONION_STAT_TYPE)) { - return MAX_ONION_STAT_TYPE; // use ntor if out of range + return MAX_ONION_STAT_TYPE; // use ntor_v3 if out of range } return type; @@ -2371,7 +2369,8 @@ onion_handshakes_requested[stat]++; /* Only relays get to record requested onionskins. */ - if (stat == ONION_HANDSHAKE_TYPE_NTOR) { + if (stat == ONION_HANDSHAKE_TYPE_NTOR || + stat == ONION_HANDSHAKE_TYPE_NTOR_V3) { /* Assess if we've reached the overload general signal. */ overload_general_onionskin_assessment(); @@ -2398,7 +2397,8 @@ stats_n_onionskin_dropped[stat]++; /* Only relays get to record requested onionskins. */ - if (stat == ONION_HANDSHAKE_TYPE_NTOR) { + if (stat == ONION_HANDSHAKE_TYPE_NTOR || + stat == ONION_HANDSHAKE_TYPE_NTOR_V3) { /* Note the dropped ntor in the overload assessment object. */ overload_onionskin_assessment.n_ntor_dropped++; } @@ -2438,11 +2438,13 @@ { (void)now; log_notice(LD_HEARTBEAT, "Circuit handshake stats since last time: " - "%d/%d TAP, %d/%d NTor.", + "%d/%d TAP, %d/%d NTor, %d/%d NTor (v3).", onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_TAP], onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP], onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR], - onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR]); + onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR], + onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR_V3], + onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR_V3]); memset(onion_handshakes_assigned, 0, sizeof(onion_handshakes_assigned)); memset(onion_handshakes_requested, 0, sizeof(onion_handshakes_requested)); } @@ -2816,6 +2818,8 @@ switch (type) { case PADDING_TYPE_DROP: padding_current.write_drop_cell_count++; + /* Padding stats get reset thus why we have two counters. */ + relay_circ_n_drop_cell_received++; break; case PADDING_TYPE_CELL: padding_current.write_pad_cell_count++; @@ -3023,6 +3027,13 @@ OVERLOAD_ONIONSKIN_NTOR_PERIOD_SECS_MAX); } +/** Relay Only: return the total number of DROP cell received. */ +uint64_t +rep_hist_get_drop_cell_received_count(void) +{ + return relay_circ_n_drop_cell_received; +} + #ifdef TOR_UNIT_TESTS /* only exists for unit tests: get HSv2 stats object */ const hs_v2_stats_t * diff -Nru tor-0.4.8.16/src/feature/stats/rephist.h tor-0.4.9.6/src/feature/stats/rephist.h --- tor-0.4.8.16/src/feature/stats/rephist.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/feature/stats/rephist.h 2026-03-25 14:30:34.000000000 +0000 @@ -102,8 +102,8 @@ void rep_hist_consensus_has_changed(const networkstatus_t *ns); /** We combine ntor and ntorv3 stats, so we have 3 stat types: - * tap, fast, and ntor. The max type is ntor (2) */ -#define MAX_ONION_STAT_TYPE ONION_HANDSHAKE_TYPE_NTOR + * tap, fast, and ntor. The max type is ntor_v3 (3) */ +#define MAX_ONION_STAT_TYPE MAX_ONION_HANDSHAKE_TYPE extern uint64_t rephist_total_alloc; extern uint32_t rephist_total_num; @@ -192,6 +192,8 @@ uint64_t rep_hist_get_n_read_limit_reached(void); uint64_t rep_hist_get_n_write_limit_reached(void); +uint64_t rep_hist_get_drop_cell_received_count(void); + #ifdef TOR_UNIT_TESTS struct hs_v2_stats_t; const struct hs_v2_stats_t *rep_hist_get_hs_v2_stats(void); diff -Nru tor-0.4.8.16/src/lib/cc/compat_compiler.h tor-0.4.9.6/src/lib/cc/compat_compiler.h --- tor-0.4.8.16/src/lib/cc/compat_compiler.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/cc/compat_compiler.h 2026-03-25 14:30:34.000000000 +0000 @@ -79,6 +79,12 @@ #define FALLTHROUGH #endif +#if defined(HAVE_ATTR_NONSTRING) +#define NONSTRING __attribute__((nonstring)) +#else +#define NONSTRING +#endif + /* What GCC do we have? */ #ifdef __GNUC__ #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) diff -Nru tor-0.4.8.16/src/lib/compress/compress.c tor-0.4.9.6/src/lib/compress/compress.c --- tor-0.4.8.16/src/lib/compress/compress.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/compress/compress.c 2026-03-25 14:30:34.000000000 +0000 @@ -53,9 +53,12 @@ * MAX_UNCOMPRESSION_FACTOR. Within those parameters, there's a reasonably * large range of possible values. IMO, anything over 8 is probably safe; IMO * anything under 50 is probably sufficient. + * + * 2025-10-01: (ahf) Bumped to 5 MB to avoid the situation described in + * tor#40739. */ #define MAX_UNCOMPRESSION_FACTOR 25 -#define CHECK_FOR_COMPRESSION_BOMB_AFTER (1024*64) +#define CHECK_FOR_COMPRESSION_BOMB_AFTER (5 * 1024 * 1024) /** @} */ /** Return true if uncompressing an input of size in_size to an input of @@ -66,11 +69,13 @@ if (size_in == 0 || size_out < CHECK_FOR_COMPRESSION_BOMB_AFTER) return 0; - if (size_out / size_in > MAX_UNCOMPRESSION_FACTOR) { + double compression_factor = (double)size_out / size_in; + if (compression_factor > MAX_UNCOMPRESSION_FACTOR) { log_warn(LD_GENERAL, "Detected possible compression bomb with " - "input size = %"TOR_PRIuSZ " and output size = %"TOR_PRIuSZ, - size_in, size_out); + "input size = %"TOR_PRIuSZ" and output size = %"TOR_PRIuSZ" " + "(compression factor = %.2f)", + size_in, size_out, compression_factor); return 1; } diff -Nru tor-0.4.8.16/src/lib/conf/include.am tor-0.4.9.6/src/lib/conf/include.am --- tor-0.4.8.16/src/lib/conf/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/conf/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -1,7 +1,7 @@ # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ - src/lib/conf/confdecl.h \ - src/lib/conf/conftesting.h \ - src/lib/conf/conftypes.h \ + src/lib/conf/confdecl.h \ + src/lib/conf/conftesting.h \ + src/lib/conf/conftypes.h \ src/lib/conf/confmacros.h diff -Nru tor-0.4.8.16/src/lib/confmgt/include.am tor-0.4.9.6/src/lib/confmgt/include.am --- tor-0.4.8.16/src/lib/confmgt/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/confmgt/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -6,10 +6,10 @@ # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_confmgt_a_SOURCES = \ - src/lib/confmgt/confmgt.c \ - src/lib/confmgt/structvar.c \ - src/lib/confmgt/type_defs.c \ - src/lib/confmgt/typedvar.c \ + src/lib/confmgt/confmgt.c \ + src/lib/confmgt/structvar.c \ + src/lib/confmgt/type_defs.c \ + src/lib/confmgt/typedvar.c \ src/lib/confmgt/unitparse.c src_lib_libtor_confmgt_testing_a_SOURCES = \ diff -Nru tor-0.4.8.16/src/lib/crypt_ops/aes.h tor-0.4.9.6/src/lib/crypt_ops/aes.h --- tor-0.4.8.16/src/lib/crypt_ops/aes.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/aes.h 2026-03-25 14:30:34.000000000 +0000 @@ -15,17 +15,31 @@ #include "lib/cc/torint.h" #include "lib/malloc/malloc.h" +#include "lib/testsupport/testsupport.h" typedef struct aes_cnt_cipher_t aes_cnt_cipher_t; aes_cnt_cipher_t* aes_new_cipher(const uint8_t *key, const uint8_t *iv, int key_bits); +void aes_cipher_set_iv_aligned(aes_cnt_cipher_t *cipher_, const uint8_t *iv); +void aes_cipher_set_key(aes_cnt_cipher_t *cipher_, + const uint8_t *key, int key_bits); void aes_cipher_free_(aes_cnt_cipher_t *cipher); #define aes_cipher_free(cipher) \ FREE_AND_NULL(aes_cnt_cipher_t, aes_cipher_free_, (cipher)) void aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len); -int evaluate_evp_for_aes(int force_value); -int evaluate_ctr_for_aes(void); +#ifdef USE_AES_RAW +typedef struct aes_raw_t aes_raw_t; + +aes_raw_t *aes_raw_new(const uint8_t *key, int key_bits, bool encrypt); +void aes_raw_set_key(aes_raw_t **cipher, const uint8_t *key, + int key_bits, bool encrypt); +void aes_raw_free_(aes_raw_t *cipher); +#define aes_raw_free(cipher) \ + FREE_AND_NULL(aes_raw_t, aes_raw_free_, (cipher)) +void aes_raw_encrypt(const aes_raw_t *cipher, uint8_t *block); +void aes_raw_decrypt(const aes_raw_t *cipher, uint8_t *block); +#endif #endif /* !defined(TOR_AES_H) */ diff -Nru tor-0.4.8.16/src/lib/crypt_ops/aes_nss.c tor-0.4.9.6/src/lib/crypt_ops/aes_nss.c --- tor-0.4.8.16/src/lib/crypt_ops/aes_nss.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/aes_nss.c 2026-03-25 14:30:34.000000000 +0000 @@ -9,6 +9,9 @@ * \brief Use NSS to implement AES_CTR. **/ +#define USE_AES_RAW +#define TOR_AES_PRIVATE + #include "orconfig.h" #include "lib/crypt_ops/aes.h" #include "lib/crypt_ops/crypto_nss_mgt.h" @@ -20,9 +23,18 @@ #include ENABLE_GCC_WARNING("-Wstrict-prototypes") -aes_cnt_cipher_t * -aes_new_cipher(const uint8_t *key, const uint8_t *iv, - int key_bits) +struct aes_cnt_cipher_t { + PK11Context *context; + // We need to keep a copy of the key here since we can't set the IV only. + // It would be nice to fix that, but NSS doesn't see a huge number of + // users. + uint8_t kbytes; + uint8_t key[32]; +}; + +static PK11Context * +aes_new_cipher_internal(const uint8_t *key, const uint8_t *iv, + int key_bits) { const CK_MECHANISM_TYPE ckm = CKM_AES_CTR; SECItem keyItem = { .type = siBuffer, @@ -65,7 +77,18 @@ PK11_FreeSlot(slot); tor_assert(result); - return (aes_cnt_cipher_t *)result; + return result; +} + +aes_cnt_cipher_t * +aes_new_cipher(const uint8_t *key, const uint8_t *iv, + int key_bits) +{ + aes_cnt_cipher_t *cipher = tor_malloc_zero(sizeof(*cipher)); + cipher->context = aes_new_cipher_internal(key, iv, key_bits); + cipher->kbytes = key_bits / 8; + memcpy(cipher->key, key, cipher->kbytes); + return cipher; } void @@ -73,7 +96,34 @@ { if (!cipher) return; - PK11_DestroyContext((PK11Context*) cipher, PR_TRUE); + PK11_DestroyContext(cipher->context, PR_TRUE); + memwipe(cipher, 0, sizeof(*cipher)); + tor_free(cipher); +} + +void +aes_cipher_set_iv_aligned(aes_cnt_cipher_t *cipher, const uint8_t *iv) +{ + // For NSS, I could not find a method to change the IV + // of an existing context. Maybe I missed one? + PK11_DestroyContext(cipher->context, PR_TRUE); + cipher->context = aes_new_cipher_internal(cipher->key, iv, + 8*(int)cipher->kbytes); +} + +void +aes_cipher_set_key(aes_cnt_cipher_t *cipher, + const uint8_t *key, int key_bits) +{ + const uint8_t iv[16] = {0}; + // For NSS, I could not find a method to change the key + // of an existing context. Maybe I missed one? + PK11_DestroyContext(cipher->context, PR_TRUE); + memwipe(cipher->key, 0, sizeof(cipher->key)); + + cipher->context = aes_new_cipher_internal(key, iv, key_bits); + cipher->kbytes = key_bits / 8; + memcpy(cipher->key, key, cipher->kbytes); } void @@ -82,25 +132,90 @@ tor_assert(len_ <= INT_MAX); SECStatus s; - PK11Context *ctx = (PK11Context*)cipher; unsigned char *data = (unsigned char *)data_; int len = (int) len_; int result_len = 0; - s = PK11_CipherOp(ctx, data, &result_len, len, data, len); + s = PK11_CipherOp(cipher->context, data, &result_len, len, data, len); tor_assert(s == SECSuccess); tor_assert(result_len == len); } -int -evaluate_evp_for_aes(int force_value) +aes_raw_t * +aes_raw_new(const uint8_t *key, int key_bits, bool encrypt) { - (void)force_value; - return 0; -} + const CK_MECHANISM_TYPE ckm = CKM_AES_ECB; + SECItem keyItem = { .type = siBuffer, // ???? + .data = (unsigned char *)key, + .len = (key_bits / 8) }; + SECItem ivItem = { .type = siBuffer, + .data = NULL, + .len = 0 }; + PK11SlotInfo *slot = NULL; + PK11SymKey *keyObj = NULL; + SECItem *ivObj = NULL; + PK11Context *result = NULL; + + slot = PK11_GetBestSlot(ckm, NULL); + if (!slot) + goto err; + + CK_ATTRIBUTE_TYPE mode = encrypt ? CKA_ENCRYPT : CKA_DECRYPT; + + keyObj = PK11_ImportSymKey(slot, ckm, PK11_OriginUnwrap, + mode, &keyItem, NULL); + if (!keyObj) + goto err; + + ivObj = PK11_ParamFromIV(ckm, &ivItem); + if (!ivObj) + goto err; + + PORT_SetError(SEC_ERROR_IO); + result = PK11_CreateContextBySymKey(ckm, mode, keyObj, ivObj); + + err: -int -evaluate_ctr_for_aes(void) + if (ivObj) + SECITEM_FreeItem(ivObj, PR_TRUE); + if (keyObj) + PK11_FreeSymKey(keyObj); + if (slot) + PK11_FreeSlot(slot); + + tor_assert(result); + return (aes_raw_t *)result; +} +void +aes_raw_free_(aes_raw_t *cipher_) +{ + if (!cipher_) + return; + PK11Context *ctx = (PK11Context*)cipher_; + PK11_DestroyContext(ctx, PR_TRUE); +} +void +aes_raw_set_key(aes_raw_t **cipher, const uint8_t *key, + int key_bits, bool encrypt) +{ + // For NSS, I could not find a method to change the key + // of an existing context. + aes_raw_free(*cipher); + *cipher = aes_raw_new(key, key_bits, encrypt); +} +void +aes_raw_encrypt(const aes_raw_t *cipher, uint8_t *block) +{ + SECStatus s; + PK11Context *ctx = (PK11Context*)cipher; + int result_len = 0; + s = PK11_CipherOp(ctx, block, &result_len, 16, block, 16); + tor_assert(s == SECSuccess); + tor_assert(result_len == 16); +} +void +aes_raw_decrypt(const aes_raw_t *cipher, uint8_t *block) { - return 0; + /* This is the same function call for NSS. */ + aes_raw_encrypt(cipher, block); } diff -Nru tor-0.4.8.16/src/lib/crypt_ops/aes_openssl.c tor-0.4.9.6/src/lib/crypt_ops/aes_openssl.c --- tor-0.4.8.16/src/lib/crypt_ops/aes_openssl.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/aes_openssl.c 2026-03-25 14:30:34.000000000 +0000 @@ -9,6 +9,9 @@ * \brief Use OpenSSL to implement AES_CTR. **/ +#define USE_AES_RAW +#define TOR_AES_PRIVATE + #include "orconfig.h" #include "lib/crypt_ops/aes.h" #include "lib/crypt_ops/crypto_util.h" @@ -24,10 +27,6 @@ #include #include "lib/crypt_ops/crypto_openssl_mgt.h" -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,0) -#error "We require OpenSSL >= 1.0.0" -#endif - DISABLE_GCC_WARNING("-Wredundant-decls") #include @@ -42,36 +41,43 @@ #include "lib/log/log.h" #include "lib/ctime/di_ops.h" -#ifdef OPENSSL_NO_ENGINE -/* Android's OpenSSL seems to have removed all of its Engine support. */ -#define DISABLE_ENGINES +/* Cached values of our EVP_CIPHER items. If we don't pre-fetch them, + * then EVP_CipherInit calls EVP_CIPHER_fetch itself, + * which is surprisingly expensive. + */ +static const EVP_CIPHER *aes128ctr = NULL; +static const EVP_CIPHER *aes192ctr = NULL; +static const EVP_CIPHER *aes256ctr = NULL; +static const EVP_CIPHER *aes128ecb = NULL; +static const EVP_CIPHER *aes192ecb = NULL; +static const EVP_CIPHER *aes256ecb = NULL; + +#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(3,0,0) \ + && !defined(LIBRESSL_VERSION_NUMBER) +#define RESOLVE_CIPHER(c) \ + EVP_CIPHER_fetch(NULL, OBJ_nid2sn(EVP_CIPHER_get_nid(c)), "") +#else +#define RESOLVE_CIPHER(c) (c) #endif -/* We have five strategies for implementing AES counter mode. - * - * Best with x86 and x86_64: Use EVP_aes_*_ctr() and EVP_EncryptUpdate(). - * This is possible with OpenSSL 1.0.1, where the counter-mode implementation - * can use bit-sliced or vectorized AES or AESNI as appropriate. - * - * Otherwise: Pick the best possible AES block implementation that OpenSSL - * gives us, and the best possible counter-mode implementation, and combine - * them. +/** + * Pre-fetch the versions of every AES cipher with its associated provider. */ -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,1,0) - -/* With newer OpenSSL versions, the older fallback modes don't compile. So - * don't use them, even if we lack specific acceleration. */ - -#define USE_EVP_AES_CTR - -#elif OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,0,1) && \ - (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || \ - defined(_M_AMD64) || defined(_M_X64) || defined(__INTEL__)) - -#define USE_EVP_AES_CTR - -#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,1,0) || ... */ +static void +init_ciphers(void) +{ + aes128ctr = RESOLVE_CIPHER(EVP_aes_128_ctr()); + aes192ctr = RESOLVE_CIPHER(EVP_aes_192_ctr()); + aes256ctr = RESOLVE_CIPHER(EVP_aes_256_ctr()); + aes128ecb = RESOLVE_CIPHER(EVP_aes_128_ecb()); + aes192ecb = RESOLVE_CIPHER(EVP_aes_192_ecb()); + aes256ecb = RESOLVE_CIPHER(EVP_aes_256_ecb()); +} +#define INIT_CIPHERS() STMT_BEGIN { \ + if (PREDICT_UNLIKELY(NULL == aes128ctr)) { \ + init_ciphers(); \ + } \ + } STMT_END /* We have 2 strategies for getting the AES block cipher: Via OpenSSL's * AES_encrypt function, or via OpenSSL's EVP_EncryptUpdate function. @@ -92,19 +98,18 @@ * make sure that we have a fixed version.) */ -#ifdef USE_EVP_AES_CTR - /* We don't actually define the struct here. */ aes_cnt_cipher_t * aes_new_cipher(const uint8_t *key, const uint8_t *iv, int key_bits) { + INIT_CIPHERS(); EVP_CIPHER_CTX *cipher = EVP_CIPHER_CTX_new(); const EVP_CIPHER *c = NULL; switch (key_bits) { - case 128: c = EVP_aes_128_ctr(); break; - case 192: c = EVP_aes_192_ctr(); break; - case 256: c = EVP_aes_256_ctr(); break; + case 128: c = aes128ctr; break; + case 192: c = aes192ctr; break; + case 256: c = aes256ctr; break; default: tor_assert_unreached(); // LCOV_EXCL_LINE } EVP_EncryptInit(cipher, c, key, iv); @@ -116,12 +121,46 @@ if (!cipher_) return; EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_; -#ifdef OPENSSL_1_1_API EVP_CIPHER_CTX_reset(cipher); + EVP_CIPHER_CTX_free(cipher); +} + +/** Changes the key of the cipher; + * sets the IV to 0. + */ +void +aes_cipher_set_key(aes_cnt_cipher_t *cipher_, const uint8_t *key, int key_bits) +{ + EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_; + uint8_t iv[16] = {0}; + const EVP_CIPHER *c = NULL; + switch (key_bits) { + case 128: c = aes128ctr; break; + case 192: c = aes192ctr; break; + case 256: c = aes256ctr; break; + default: tor_assert_unreached(); // LCOV_EXCL_LINE + } + + // No need to call EVP_CIPHER_CTX_Reset here; EncryptInit already + // does it for us. + EVP_EncryptInit(cipher, c, key, iv); +} +/** Change the IV of this stream cipher without changing the key. + * + * Requires that the cipher stream position is at an even multiple of 16 bytes. + */ +void +aes_cipher_set_iv_aligned(aes_cnt_cipher_t *cipher_, const uint8_t *iv) +{ + EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *) cipher_; +#ifdef LIBRESSL_VERSION_NUMBER + EVP_CIPHER_CTX_set_iv(cipher, iv, 16); #else - EVP_CIPHER_CTX_cleanup(cipher); + // We would have to do this if the cipher's position were not aligned: + // EVP_CIPHER_CTX_set_num(cipher, 0); + + memcpy(EVP_CIPHER_CTX_iv_noconst(cipher), iv, 16); #endif - EVP_CIPHER_CTX_free(cipher); } void aes_crypt_inplace(aes_cnt_cipher_t *cipher_, char *data, size_t len) @@ -134,276 +173,105 @@ EVP_EncryptUpdate(cipher, (unsigned char*)data, &outl, (unsigned char*)data, (int)len); } -int -evaluate_evp_for_aes(int force_val) -{ - (void) force_val; - log_info(LD_CRYPTO, "This version of OpenSSL has a known-good EVP " - "counter-mode implementation. Using it."); - return 0; -} -int -evaluate_ctr_for_aes(void) -{ - return 0; -} -#else /* !defined(USE_EVP_AES_CTR) */ - -/*======================================================================*/ -/* Interface to AES code, and counter implementation */ - -/** Implements an AES counter-mode cipher. */ -struct aes_cnt_cipher_t { -/** This next element (however it's defined) is the AES key. */ - union { - EVP_CIPHER_CTX evp; - AES_KEY aes; - } key; - -#if !defined(WORDS_BIGENDIAN) -#define USING_COUNTER_VARS - /** These four values, together, implement a 128-bit counter, with - * counter0 as the low-order word and counter3 as the high-order word. */ - uint32_t counter3; - uint32_t counter2; - uint32_t counter1; - uint32_t counter0; -#endif /* !defined(WORDS_BIGENDIAN) */ - - union { - /** The counter, in big-endian order, as bytes. */ - uint8_t buf[16]; - /** The counter, in big-endian order, as big-endian words. Note that - * on big-endian platforms, this is redundant with counter3...0, - * so we just use these values instead. */ - uint32_t buf32[4]; - } ctr_buf; - - /** The encrypted value of ctr_buf. */ - uint8_t buf[16]; - /** Our current stream position within buf. */ - unsigned int pos; - - /** True iff we're using the evp implementation of this cipher. */ - uint8_t using_evp; -}; - -/** True iff we should prefer the EVP implementation for AES, either because - * we're testing it or because we have hardware acceleration configured */ -static int should_use_EVP = 0; - -/** Check whether we should use the EVP interface for AES. If force_val - * is nonnegative, we use use EVP iff it is true. Otherwise, we use EVP - * if there is an engine enabled for aes-ecb. */ -int -evaluate_evp_for_aes(int force_val) -{ - ENGINE *e; - - if (force_val >= 0) { - should_use_EVP = force_val; - return 0; - } -#ifdef DISABLE_ENGINES - should_use_EVP = 0; -#else - e = ENGINE_get_cipher_engine(NID_aes_128_ecb); - - if (e) { - log_info(LD_CRYPTO, "AES engine \"%s\" found; using EVP_* functions.", - ENGINE_get_name(e)); - should_use_EVP = 1; - } else { - log_info(LD_CRYPTO, "No AES engine found; using AES_* functions."); - should_use_EVP = 0; - } -#endif /* defined(DISABLE_ENGINES) */ - - return 0; -} -/** Test the OpenSSL counter mode implementation to see whether it has the - * counter-mode bug from OpenSSL 1.0.0. If the implementation works, then - * we will use it for future encryption/decryption operations. +/* ======== + * Functions for "raw" (ECB) AES. * - * We can't just look at the OpenSSL version, since some distributions update - * their OpenSSL packages without changing the version number. - **/ -int -evaluate_ctr_for_aes(void) -{ - /* Result of encrypting an all-zero block with an all-zero 128-bit AES key. - * This should be the same as encrypting an all-zero block with an all-zero - * 128-bit AES key in counter mode, starting at position 0 of the stream. - */ - static const unsigned char encrypt_zero[] = - "\x66\xe9\x4b\xd4\xef\x8a\x2c\x3b\x88\x4c\xfa\x59\xca\x34\x2b\x2e"; - unsigned char zero[16]; - unsigned char output[16]; - unsigned char ivec[16]; - unsigned char ivec_tmp[16]; - unsigned int pos, i; - AES_KEY key; - memset(zero, 0, sizeof(zero)); - memset(ivec, 0, sizeof(ivec)); - AES_set_encrypt_key(zero, 128, &key); - - pos = 0; - /* Encrypting a block one byte at a time should make the error manifest - * itself for known bogus openssl versions. */ - for (i=0; i<16; ++i) - AES_ctr128_encrypt(&zero[i], &output[i], 1, &key, ivec, ivec_tmp, &pos); - - if (fast_memneq(output, encrypt_zero, 16)) { - /* Counter mode is buggy */ - /* LCOV_EXCL_START */ - log_err(LD_CRYPTO, "This OpenSSL has a buggy version of counter mode; " - "quitting tor."); - exit(1); // exit ok: openssl is broken. - /* LCOV_EXCL_STOP */ - } - return 0; -} - -#if !defined(USING_COUNTER_VARS) -#define COUNTER(c, n) ((c)->ctr_buf.buf32[3-(n)]) -#else -#define COUNTER(c, n) ((c)->counter ## n) -#endif - -static void aes_set_key(aes_cnt_cipher_t *cipher, const uint8_t *key, - int key_bits); -static void aes_set_iv(aes_cnt_cipher_t *cipher, const uint8_t *iv); + * I'm choosing the name "raw" here because ECB is not a mode; + * it's a disaster. The only way to use this safely is + * within a real construction. + */ /** - * Return a newly allocated counter-mode AES128 cipher implementation, - * using the 128-bit key key and the 128-bit IV iv. + * Create a new instance of AES using a key of length 'key_bits' + * for raw block encryption. + * + * This is even more low-level than counter-mode, and you should + * only use it with extreme caution. */ -aes_cnt_cipher_t* -aes_new_cipher(const uint8_t *key, const uint8_t *iv, int bits) +aes_raw_t * +aes_raw_new(const uint8_t *key, int key_bits, bool encrypt) { - aes_cnt_cipher_t* result = tor_malloc_zero(sizeof(aes_cnt_cipher_t)); - - aes_set_key(result, key, bits); - aes_set_iv(result, iv); + INIT_CIPHERS(); + EVP_CIPHER_CTX *cipher = EVP_CIPHER_CTX_new(); + tor_assert(cipher); + const EVP_CIPHER *c = NULL; + switch (key_bits) { + case 128: c = aes128ecb; break; + case 192: c = aes192ecb; break; + case 256: c = aes256ecb; break; + default: tor_assert_unreached(); + } - return result; + // No need to call EVP_CIPHER_CTX_Reset here; EncryptInit already + // does it for us. + int r = EVP_CipherInit(cipher, c, key, NULL, encrypt); + tor_assert(r == 1); + EVP_CIPHER_CTX_set_padding(cipher, 0); + return (aes_raw_t *)cipher; } - -/** Set the key of cipher to key, which is - * key_bits bits long (must be 128, 192, or 256). Also resets - * the counter to 0. +/** + * Replace the key on an existing aes_raw_t. + * + * This may be faster than freeing and reallocating. */ -static void -aes_set_key(aes_cnt_cipher_t *cipher, const uint8_t *key, int key_bits) +void +aes_raw_set_key(aes_raw_t **cipher_, const uint8_t *key, + int key_bits, bool encrypt) { - if (should_use_EVP) { - const EVP_CIPHER *c = 0; - switch (key_bits) { - case 128: c = EVP_aes_128_ecb(); break; - case 192: c = EVP_aes_192_ecb(); break; - case 256: c = EVP_aes_256_ecb(); break; - default: tor_assert(0); // LCOV_EXCL_LINE - } - EVP_EncryptInit(&cipher->key.evp, c, key, NULL); - cipher->using_evp = 1; - } else { - AES_set_encrypt_key(key, key_bits,&cipher->key.aes); - cipher->using_evp = 0; + const EVP_CIPHER *c = *(EVP_CIPHER**) cipher_; + switch (key_bits) { + case 128: c = aes128ecb; break; + case 192: c = aes192ecb; break; + case 256: c = aes256ecb; break; + default: tor_assert_unreached(); } - -#ifdef USING_COUNTER_VARS - cipher->counter0 = 0; - cipher->counter1 = 0; - cipher->counter2 = 0; - cipher->counter3 = 0; -#endif /* defined(USING_COUNTER_VARS) */ - - memset(cipher->ctr_buf.buf, 0, sizeof(cipher->ctr_buf.buf)); - - cipher->pos = 0; - - memset(cipher->buf, 0, sizeof(cipher->buf)); + aes_raw_t *cipherp = *cipher_; + EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *)cipherp; + int r = EVP_CipherInit(cipher, c, key, NULL, encrypt); + tor_assert(r == 1); + EVP_CIPHER_CTX_set_padding(cipher, 0); } -/** Release storage held by cipher +/** + * Release storage held by 'cipher'. */ void -aes_cipher_free_(aes_cnt_cipher_t *cipher) +aes_raw_free_(aes_raw_t *cipher_) { - if (!cipher) + if (!cipher_) return; - if (cipher->using_evp) { - EVP_CIPHER_CTX_cleanup(&cipher->key.evp); - } - memwipe(cipher, 0, sizeof(aes_cnt_cipher_t)); - tor_free(cipher); -} - -#if defined(USING_COUNTER_VARS) -#define UPDATE_CTR_BUF(c, n) STMT_BEGIN \ - (c)->ctr_buf.buf32[3-(n)] = htonl((c)->counter ## n); \ - STMT_END + EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *)cipher_; +#ifdef OPENSSL_1_1_API + EVP_CIPHER_CTX_reset(cipher); #else -#define UPDATE_CTR_BUF(c, n) -#endif /* defined(USING_COUNTER_VARS) */ - -/* Helper function to use EVP with openssl's counter-mode wrapper. */ -static void -evp_block128_fn(const uint8_t in[16], - uint8_t out[16], - const void *key) -{ - EVP_CIPHER_CTX *ctx = (void*)key; - int inl=16, outl=16; - EVP_EncryptUpdate(ctx, out, &outl, in, inl); + EVP_CIPHER_CTX_cleanup(cipher); +#endif + EVP_CIPHER_CTX_free(cipher); } - -/** Encrypt len bytes from input, storing the results in place. - * Uses the key in cipher, and advances the counter by len bytes - * as it encrypts. +#define aes_raw_free(cipher) \ + FREE_AND_NULL(aes_raw_t, aes_raw_free_, (cipher)) +/** + * Encrypt a single 16-byte block with 'cipher', + * which must have been initialized for encryption. */ void -aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len) +aes_raw_encrypt(const aes_raw_t *cipher, uint8_t *block) { - /* Note that the "128" below refers to the length of the counter, - * not the length of the AES key. */ - if (cipher->using_evp) { - /* In openssl 1.0.0, there's an if'd out EVP_aes_128_ctr in evp.h. If - * it weren't disabled, it might be better just to use that. - */ - CRYPTO_ctr128_encrypt((const unsigned char *)data, - (unsigned char *)data, - len, - &cipher->key.evp, - cipher->ctr_buf.buf, - cipher->buf, - &cipher->pos, - evp_block128_fn); - } else { - AES_ctr128_encrypt((const unsigned char *)data, - (unsigned char *)data, - len, - &cipher->key.aes, - cipher->ctr_buf.buf, - cipher->buf, - &cipher->pos); - } + int outl = 16; + int r = EVP_EncryptUpdate((EVP_CIPHER_CTX *)cipher, block, &outl, block, 16); + tor_assert(r == 1); + tor_assert(outl == 16); } - -/** Reset the 128-bit counter of cipher to the 16-bit big-endian value - * in iv. */ -static void -aes_set_iv(aes_cnt_cipher_t *cipher, const uint8_t *iv) +/** + * Decrypt a single 16-byte block with 'cipher', + * which must have been initialized for decryption. + */ +void +aes_raw_decrypt(const aes_raw_t *cipher, uint8_t *block) { -#ifdef USING_COUNTER_VARS - cipher->counter3 = tor_ntohl(get_uint32(iv)); - cipher->counter2 = tor_ntohl(get_uint32(iv+4)); - cipher->counter1 = tor_ntohl(get_uint32(iv+8)); - cipher->counter0 = tor_ntohl(get_uint32(iv+12)); -#endif /* defined(USING_COUNTER_VARS) */ - cipher->pos = 0; - memcpy(cipher->ctr_buf.buf, iv, 16); + int outl = 16; + int r = EVP_DecryptUpdate((EVP_CIPHER_CTX *)cipher, block, &outl, block, 16); + tor_assert(r == 1); + tor_assert(outl == 16); } - -#endif /* defined(USE_EVP_AES_CTR) */ diff -Nru tor-0.4.8.16/src/lib/crypt_ops/compat_openssl.h tor-0.4.9.6/src/lib/crypt_ops/compat_openssl.h --- tor-0.4.8.16/src/lib/crypt_ops/compat_openssl.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/compat_openssl.h 2026-03-25 14:30:34.000000000 +0000 @@ -20,37 +20,13 @@ * \brief compatibility definitions for working with different openssl forks **/ -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,1) -#error "We require OpenSSL >= 1.0.1" -#endif - -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) -/* We define this macro if we're trying to build with the majorly refactored - * API in OpenSSL 1.1 */ -#define OPENSSL_1_1_API -#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) && ... */ - -/* LibreSSL claims to be OpenSSL 2.0 but lacks these OpenSSL 1.1 APIs */ -#if !defined(OPENSSL_1_1_API) || defined(LIBRESSL_VERSION_NUMBER) +/* LibreSSL claims to be OpenSSL 2.0 but lacks this OpenSSL 1.1 API. */ +#if defined(LIBRESSL_VERSION_NUMBER) #define RAND_OpenSSL() RAND_SSLeay() -#define STATE_IS_SW_SERVER_HELLO(st) \ - (((st) == SSL3_ST_SW_SRVR_HELLO_A) || \ - ((st) == SSL3_ST_SW_SRVR_HELLO_B)) #define OSSL_HANDSHAKE_STATE int -#define CONST_IF_OPENSSL_1_1_API -#else -#define STATE_IS_SW_SERVER_HELLO(st) \ - ((st) == TLS_ST_SW_SRVR_HELLO) -#define CONST_IF_OPENSSL_1_1_API const #endif -/* OpenSSL 1.1 and LibreSSL both have these APIs */ -#ifndef OPENSSL_1_1_API -#define OpenSSL_version(v) SSLeay_version(v) -#define tor_OpenSSL_version_num() SSLeay() -#else /* defined(OPENSSL_1_1_API) */ #define tor_OpenSSL_version_num() OpenSSL_version_num() -#endif /* !defined(OPENSSL_1_1_API) */ #endif /* defined(ENABLE_OPENSSL) */ diff -Nru tor-0.4.8.16/src/lib/crypt_ops/crypto_dh.c tor-0.4.9.6/src/lib/crypt_ops/crypto_dh.c --- tor-0.4.8.16/src/lib/crypt_ops/crypto_dh.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/crypto_dh.c 2026-03-25 14:30:34.000000000 +0000 @@ -21,16 +21,20 @@ /** Our DH 'g' parameter */ const unsigned DH_GENERATOR = 2; -/** This is the 1024-bit safe prime that Apache uses for its DH stuff; see - * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this - * prime. +/** This is ffdhe2048 from RFC 7919. */ const char TLS_DH_PRIME[] = - "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98" - "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A" - "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7" - "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68" - "B0E7393E0F24218EB3"; + "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1" + "D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF9" + "7D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD6561" + "2433F51F5F066ED0856365553DED1AF3B557135E7F57C935" + "984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE735" + "30ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FB" + "B96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB19" + "0B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F61" + "9172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD73" + "3BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA" + "886B423861285C97FFFFFFFFFFFFFFFF"; /** * This is from rfc2409, section 6.2. It's a safe prime, and * supposedly it equals: diff -Nru tor-0.4.8.16/src/lib/crypt_ops/crypto_dh.h tor-0.4.9.6/src/lib/crypt_ops/crypto_dh.h --- tor-0.4.8.16/src/lib/crypt_ops/crypto_dh.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/crypto_dh.h 2026-03-25 14:30:34.000000000 +0000 @@ -61,4 +61,6 @@ void crypto_dh_free_all_nss(void); #endif +#define DH_TLS_KEY_BITS 2048 + #endif /* !defined(TOR_CRYPTO_DH_H) */ diff -Nru tor-0.4.8.16/src/lib/crypt_ops/crypto_dh_nss.c tor-0.4.9.6/src/lib/crypt_ops/crypto_dh_nss.c --- tor-0.4.8.16/src/lib/crypt_ops/crypto_dh_nss.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/crypto_dh_nss.c 2026-03-25 14:30:34.000000000 +0000 @@ -25,7 +25,7 @@ static int dh_initialized = 0; static SECKEYDHParams tls_dh_param, circuit_dh_param; -static unsigned char tls_dh_prime_data[DH1024_KEY_LEN]; +static unsigned char tls_dh_prime_data[DH2048_KEY_LEN]; static unsigned char circuit_dh_prime_data[DH1024_KEY_LEN]; static unsigned char dh_generator_data[1]; @@ -39,7 +39,7 @@ r = base16_decode((char*)tls_dh_prime_data, sizeof(tls_dh_prime_data), TLS_DH_PRIME, strlen(TLS_DH_PRIME)); - tor_assert(r == DH1024_KEY_LEN); + tor_assert(r == DH2048_KEY_LEN); r = base16_decode((char*)circuit_dh_prime_data, sizeof(circuit_dh_prime_data), OAKLEY_PRIME_2, strlen(OAKLEY_PRIME_2)); @@ -47,7 +47,7 @@ dh_generator_data[0] = DH_GENERATOR; tls_dh_param.prime.data = tls_dh_prime_data; - tls_dh_param.prime.len = DH1024_KEY_LEN; + tls_dh_param.prime.len = DH2048_KEY_LEN; tls_dh_param.base.data = dh_generator_data; tls_dh_param.base.len = 1; diff -Nru tor-0.4.8.16/src/lib/crypt_ops/crypto_dh_openssl.c tor-0.4.9.6/src/lib/crypt_ops/crypto_dh_openssl.c --- tor-0.4.8.16/src/lib/crypt_ops/crypto_dh_openssl.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/crypto_dh_openssl.c 2026-03-25 14:30:34.000000000 +0000 @@ -27,7 +27,8 @@ #include #ifndef ENABLE_NSS -static int tor_check_dh_key(int severity, const BIGNUM *bn); +static int tor_check_dh_key(int severity, const BIGNUM *bn, + const BIGNUM *dh_p); /** A structure to hold the first half (x, g^x) of a Diffie-Hellman handshake * while we're waiting for the second.*/ @@ -60,7 +61,7 @@ /* Copy into a temporary DH object, just so that DH_check() can be called. */ if (!(dh = DH_new())) goto out; -#ifdef OPENSSL_1_1_API + BIGNUM *dh_p, *dh_g; if (!(dh_p = BN_dup(p))) goto out; @@ -68,12 +69,6 @@ goto out; if (!DH_set0_pqg(dh, dh_p, NULL, dh_g)) goto out; -#else /* !defined(OPENSSL_1_1_API) */ - if (!(dh->p = BN_dup(p))) - goto out; - if (!(dh->g = BN_dup(g))) - goto out; -#endif /* defined(OPENSSL_1_1_API) */ /* Perform the validation. */ int codes = 0; @@ -223,19 +218,12 @@ goto err; } -#ifdef OPENSSL_1_1_API - if (!DH_set0_pqg(res_dh, dh_p, NULL, dh_g)) { goto err; } if (!DH_set_length(res_dh, DH_PRIVATE_KEY_BITS)) goto err; -#else /* !defined(OPENSSL_1_1_API) */ - res_dh->p = dh_p; - res_dh->g = dh_g; - res_dh->length = DH_PRIVATE_KEY_BITS; -#endif /* defined(OPENSSL_1_1_API) */ return res_dh; @@ -276,9 +264,6 @@ int crypto_dh_generate_public(crypto_dh_t *dh) { -#ifndef OPENSSL_1_1_API - again: -#endif if (!DH_generate_key(dh->dh)) { /* LCOV_EXCL_START * To test this we would need some way to tell openssl to break DH. */ @@ -286,32 +271,19 @@ return -1; /* LCOV_EXCL_STOP */ } -#ifdef OPENSSL_1_1_API + /* OpenSSL 1.1.x doesn't appear to let you regenerate a DH key, without * recreating the DH object. I have no idea what sort of aliasing madness * can occur here, so do the check, and just bail on failure. */ const BIGNUM *pub_key, *priv_key; DH_get0_key(dh->dh, &pub_key, &priv_key); - if (tor_check_dh_key(LOG_WARN, pub_key)<0) { + if (tor_check_dh_key(LOG_WARN, pub_key, DH_get0_p(dh->dh))<0) { log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-" "the-universe chances really do happen. Treating as a failure."); return -1; } -#else /* !defined(OPENSSL_1_1_API) */ - if (tor_check_dh_key(LOG_WARN, dh->dh->pub_key)<0) { - /* LCOV_EXCL_START - * If this happens, then openssl's DH implementation is busted. */ - log_warn(LD_CRYPTO, "Weird! Our own DH key was invalid. I guess once-in-" - "the-universe chances really do happen. Trying again."); - /* Free and clear the keys, so OpenSSL will actually try again. */ - BN_clear_free(dh->dh->pub_key); - BN_clear_free(dh->dh->priv_key); - dh->dh->pub_key = dh->dh->priv_key = NULL; - goto again; - /* LCOV_EXCL_STOP */ - } -#endif /* defined(OPENSSL_1_1_API) */ + return 0; } @@ -327,22 +299,14 @@ const BIGNUM *dh_pub; -#ifdef OPENSSL_1_1_API const BIGNUM *dh_priv; DH_get0_key(dh->dh, &dh_pub, &dh_priv); -#else - dh_pub = dh->dh->pub_key; -#endif /* defined(OPENSSL_1_1_API) */ if (!dh_pub) { if (crypto_dh_generate_public(dh)<0) return -1; else { -#ifdef OPENSSL_1_1_API DH_get0_key(dh->dh, &dh_pub, &dh_priv); -#else - dh_pub = dh->dh->pub_key; -#endif } } @@ -351,7 +315,7 @@ tor_assert(bytes >= 0); if (pubkey_len < (size_t)bytes) { log_warn(LD_CRYPTO, - "Weird! pubkey_len (%d) was smaller than DH1024_KEY_LEN (%d)", + "Weird! pubkey_len (%d) was smaller than key length (%d)", (int) pubkey_len, bytes); return -1; } @@ -367,21 +331,19 @@ * See http://www.cl.cam.ac.uk/ftp/users/rja14/psandqs.ps.gz for some tips. */ static int -tor_check_dh_key(int severity, const BIGNUM *bn) +tor_check_dh_key(int severity, const BIGNUM *bn, const BIGNUM *dh_p) { BIGNUM *x; char *s; tor_assert(bn); x = BN_new(); tor_assert(x); - if (BUG(!dh_param_p)) - crypto_dh_init(); //LCOV_EXCL_LINE we already checked whether we did this. BN_set_word(x, 1); if (BN_cmp(bn,x)<=0) { log_fn(severity, LD_CRYPTO, "DH key must be at least 2."); goto err; } - BN_copy(x,dh_param_p); + BN_copy(x,dh_p); BN_sub_word(x, 1); if (BN_cmp(bn,x)>=0) { log_fn(severity, LD_CRYPTO, "DH key must be at most p-2."); @@ -425,7 +387,7 @@ if (!(pubkey_bn = BN_bin2bn((const unsigned char*)pubkey, (int)pubkey_len, NULL))) goto error; - if (tor_check_dh_key(severity, pubkey_bn)<0) { + if (tor_check_dh_key(severity, pubkey_bn, DH_get0_p(dh->dh))<0) { /* Check for invalid public keys. */ log_fn(severity, LD_CRYPTO,"Rejected invalid g^x"); goto error; diff -Nru tor-0.4.8.16/src/lib/crypt_ops/crypto_hkdf.c tor-0.4.9.6/src/lib/crypt_ops/crypto_hkdf.c --- tor-0.4.8.16/src/lib/crypt_ops/crypto_hkdf.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/crypto_hkdf.c 2026-03-25 14:30:34.000000000 +0000 @@ -20,11 +20,8 @@ #ifdef ENABLE_OPENSSL #include #include - -#if defined(HAVE_ERR_LOAD_KDF_STRINGS) #include -#define HAVE_OPENSSL_HKDF 1 -#endif +#define HAVE_OPENSSL_HKDF #endif /* defined(ENABLE_OPENSSL) */ #include diff -Nru tor-0.4.8.16/src/lib/crypt_ops/crypto_init.c tor-0.4.9.6/src/lib/crypt_ops/crypto_init.c --- tor-0.4.8.16/src/lib/crypt_ops/crypto_init.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/crypto_init.c 2026-03-25 14:30:34.000000000 +0000 @@ -26,6 +26,7 @@ #include "lib/crypt_ops/crypto_options_st.h" #include "lib/conf/conftypes.h" #include "lib/log/util_bug.h" +#include "ext/polyval/polyval.h" #include "lib/subsys/subsys.h" @@ -69,6 +70,8 @@ crypto_nss_early_init(0); #endif + polyval_detect_implementation(); + if (crypto_seed_rng() < 0) return -1; if (crypto_init_siphash_key() < 0) diff -Nru tor-0.4.8.16/src/lib/crypt_ops/crypto_openssl_mgt.c tor-0.4.9.6/src/lib/crypt_ops/crypto_openssl_mgt.c --- tor-0.4.8.16/src/lib/crypt_ops/crypto_openssl_mgt.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/crypto_openssl_mgt.c 2026-03-25 14:30:34.000000000 +0000 @@ -40,19 +40,13 @@ #include -#ifndef NEW_THREAD_API -/** A number of preallocated mutexes for use by OpenSSL. */ -static tor_mutex_t **openssl_mutexes_ = NULL; -/** How many mutexes have we allocated for use by OpenSSL? */ -static int n_openssl_mutexes_ = 0; -#endif /* !defined(NEW_THREAD_API) */ +#ifdef OPENSSL_NO_ENGINE +/* Android's OpenSSL seems to have removed all of its Engine support. */ +#define DISABLE_ENGINES +#endif /** Declare STATIC functions */ STATIC char * parse_openssl_version_str(const char *raw_version); -#ifndef NEW_THREAD_API -STATIC void openssl_locking_cb_(int mode, int n, const char *file, int line); -STATIC void tor_set_openssl_thread_id(CRYPTO_THREADID *threadid); -#endif /** Log all pending crypto errors at level severity. Use * doing to describe our current activities. @@ -101,12 +95,7 @@ const char * crypto_openssl_get_version_str(void) { -#ifdef OPENSSL_VERSION const int query = OPENSSL_VERSION; -#else - /* This old name was changed around OpenSSL 1.1.0 */ - const int query = SSLEAY_VERSION; -#endif /* defined(OPENSSL_VERSION) */ if (crypto_openssl_version_str == NULL) { const char *raw_version = OpenSSL_version(query); @@ -115,8 +104,6 @@ return crypto_openssl_version_str; } -#undef QUERY_OPENSSL_VERSION - static char *crypto_openssl_header_version_str = NULL; /* Return a human-readable version of the compile-time openssl version * number. */ @@ -137,46 +124,11 @@ #endif #endif /* !defined(COCCI) */ -#ifndef NEW_THREAD_API -/** Helper: OpenSSL uses this callback to manipulate mutexes. */ -STATIC void -openssl_locking_cb_(int mode, int n, const char *file, int line) -{ - (void)file; - (void)line; - if (!openssl_mutexes_) - /* This is not a really good fix for the - * "release-freed-lock-from-separate-thread-on-shutdown" problem, but - * it can't hurt. */ - return; - if (mode & CRYPTO_LOCK) - tor_mutex_acquire(openssl_mutexes_[n]); - else - tor_mutex_release(openssl_mutexes_[n]); -} - -STATIC void -tor_set_openssl_thread_id(CRYPTO_THREADID *threadid) -{ - CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id()); -} -#endif /* !defined(NEW_THREAD_API) */ - /** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being * multithreaded. Returns 0. */ static int setup_openssl_threading(void) { -#ifndef NEW_THREAD_API - int i; - int n = CRYPTO_num_locks(); - n_openssl_mutexes_ = n; - openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *)); - for (i=0; i < n; ++i) - openssl_mutexes_[i] = tor_mutex_new(); - CRYPTO_set_locking_callback(openssl_locking_cb_); - CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id); -#endif /* !defined(NEW_THREAD_API) */ return 0; } @@ -186,39 +138,16 @@ { tor_free(crypto_openssl_version_str); tor_free(crypto_openssl_header_version_str); - - /* Destroying a locked mutex is undefined behaviour. This mutex may be - * locked, because multiple threads can access it. But we need to destroy - * it, otherwise re-initialisation will trigger undefined behaviour. - * See #31735 for details. */ -#ifndef NEW_THREAD_API - if (n_openssl_mutexes_) { - int n = n_openssl_mutexes_; - tor_mutex_t **ms = openssl_mutexes_; - int i; - openssl_mutexes_ = NULL; - n_openssl_mutexes_ = 0; - for (i=0;i=3.5 would be ideal.", + OPENSSL_VERSION_TEXT); + } +#endif + if (useAccel > 0) { if (crypto_openssl_init_engines(accelName, accelDir) < 0) return -1; @@ -389,9 +323,6 @@ return -1; } - evaluate_evp_for_aes(-1); - evaluate_ctr_for_aes(); - return 0; } @@ -399,35 +330,13 @@ void crypto_openssl_thread_cleanup(void) { -#ifndef NEW_THREAD_API - ERR_remove_thread_state(NULL); -#endif } /** Clean up global resources held by openssl. */ void crypto_openssl_global_cleanup(void) { -#ifndef OPENSSL_1_1_API - EVP_cleanup(); -#endif -#ifndef NEW_THREAD_API - ERR_remove_thread_state(NULL); -#endif -#ifndef OPENSSL_1_1_API - ERR_free_strings(); -#endif - -#ifndef DISABLE_ENGINES -#ifndef OPENSSL_1_1_API - ENGINE_cleanup(); -#endif -#endif - CONF_modules_unload(1); -#ifndef OPENSSL_1_1_API - CRYPTO_cleanup_all_ex_data(); -#endif crypto_openssl_free_all(); } diff -Nru tor-0.4.8.16/src/lib/crypt_ops/crypto_openssl_mgt.h tor-0.4.9.6/src/lib/crypt_ops/crypto_openssl_mgt.h --- tor-0.4.8.16/src/lib/crypt_ops/crypto_openssl_mgt.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/crypto_openssl_mgt.h 2026-03-25 14:30:34.000000000 +0000 @@ -49,26 +49,6 @@ #define OPENSSL_V_SERIES(a,b,c) \ OPENSSL_VER((a),(b),(c),0,0) -#ifdef OPENSSL_NO_ENGINE -/* Android's OpenSSL seems to have removed all of its Engine support. */ -#define DISABLE_ENGINES -#endif - -#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) -/* OpenSSL as of 1.1.0pre4 has an "new" thread API, which doesn't require - * setting up various callbacks. - * - * OpenSSL 1.1.0pre4 has a messed up `ERR_remove_thread_state()` prototype, - * while the previous one was restored in pre5, and the function made a no-op - * (along with a deprecated annotation, which produces a compiler warning). - * - * While it is possible to support all three versions of the thread API, - * a version that existed only for one snapshot pre-release is kind of - * pointless, so let's not. - */ -#define NEW_THREAD_API -#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) && ... */ - void crypto_openssl_log_errors(int severity, const char *doing); /* global openssl state */ diff -Nru tor-0.4.8.16/src/lib/crypt_ops/crypto_rsa_openssl.c tor-0.4.9.6/src/lib/crypt_ops/crypto_rsa_openssl.c --- tor-0.4.8.16/src/lib/crypt_ops/crypto_rsa_openssl.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/crypto_rsa_openssl.c 2026-03-25 14:30:34.000000000 +0000 @@ -47,16 +47,12 @@ int crypto_pk_key_is_private(const crypto_pk_t *k) { -#ifdef OPENSSL_1_1_API if (!k || !k->key) return 0; const BIGNUM *p, *q; RSA_get0_factors(k->key, &p, &q); return p != NULL; /* XXX/yawning: Should we check q? */ -#else /* !defined(OPENSSL_1_1_API) */ - return k && k->key && k->key->p; -#endif /* defined(OPENSSL_1_1_API) */ } /** used by tortls.c: wrap an RSA* in a crypto_pk_t. Takes ownership of @@ -212,12 +208,8 @@ const BIGNUM *e; -#ifdef OPENSSL_1_1_API const BIGNUM *n, *d; RSA_get0_key(env->key, &n, &e, &d); -#else - e = env->key->e; -#endif /* defined(OPENSSL_1_1_API) */ return BN_is_word(e, TOR_RSA_EXPONENT); } @@ -242,16 +234,9 @@ const BIGNUM *a_n, *a_e; const BIGNUM *b_n, *b_e; -#ifdef OPENSSL_1_1_API const BIGNUM *a_d, *b_d; RSA_get0_key(a->key, &a_n, &a_e, &a_d); RSA_get0_key(b->key, &b_n, &b_e, &b_d); -#else - a_n = a->key->n; - a_e = a->key->e; - b_n = b->key->n; - b_e = b->key->e; -#endif /* defined(OPENSSL_1_1_API) */ tor_assert(a_n != NULL && a_e != NULL); tor_assert(b_n != NULL && b_e != NULL); @@ -279,7 +264,6 @@ tor_assert(env); tor_assert(env->key); -#ifdef OPENSSL_1_1_API /* It's so stupid that there's no other way to check that n is valid * before calling RSA_bits(). */ @@ -288,10 +272,6 @@ tor_assert(n != NULL); return RSA_bits(env->key); -#else /* !defined(OPENSSL_1_1_API) */ - tor_assert(env->key->n); - return BN_num_bits(env->key->n); -#endif /* defined(OPENSSL_1_1_API) */ } /** Increase the reference count of env, and return it. @@ -572,11 +552,7 @@ rsa_private_key_too_long(RSA *rsa, int max_bits) { const BIGNUM *n, *e, *p, *q, *d, *dmp1, *dmq1, *iqmp; -#if defined(OPENSSL_1_1_API) && \ - (!defined(LIBRESSL_VERSION_NUMBER) || \ - LIBRESSL_VERSION_NUMBER >= OPENSSL_V_SERIES(3,5,0)) -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,1) n = RSA_get0_n(rsa); e = RSA_get0_e(rsa); p = RSA_get0_p(rsa); @@ -585,24 +561,9 @@ dmp1 = RSA_get0_dmp1(rsa); dmq1 = RSA_get0_dmq1(rsa); iqmp = RSA_get0_iqmp(rsa); -#else /* !(OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,1)) */ - /* The accessors above did not exist in openssl 1.1.0. */ - p = q = dmp1 = dmq1 = iqmp = NULL; - RSA_get0_key(rsa, &n, &e, &d); -#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,1) */ if (RSA_bits(rsa) > max_bits) return true; -#else /* !defined(OPENSSL_1_1_API) && ... */ - n = rsa->n; - e = rsa->e; - p = rsa->p; - q = rsa->q; - d = rsa->d; - dmp1 = rsa->dmp1; - dmq1 = rsa->dmq1; - iqmp = rsa->iqmp; -#endif /* defined(OPENSSL_1_1_API) && ... */ if (n && BN_num_bits(n) > max_bits) return true; diff -Nru tor-0.4.8.16/src/lib/crypt_ops/include.am tor-0.4.9.6/src/lib/crypt_ops/include.am --- tor-0.4.8.16/src/lib/crypt_ops/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/crypt_ops/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -15,14 +15,14 @@ src/lib/crypt_ops/crypto_format.c \ src/lib/crypt_ops/crypto_hkdf.c \ src/lib/crypt_ops/crypto_init.c \ - src/lib/crypt_ops/crypto_ope.c \ + src/lib/crypt_ops/crypto_ope.c \ src/lib/crypt_ops/crypto_pwbox.c \ src/lib/crypt_ops/crypto_rand.c \ src/lib/crypt_ops/crypto_rand_fast.c \ src/lib/crypt_ops/crypto_rand_numeric.c \ src/lib/crypt_ops/crypto_rsa.c \ src/lib/crypt_ops/crypto_s2k.c \ - src/lib/crypt_ops/crypto_util.c \ + src/lib/crypt_ops/crypto_util.c \ src/lib/crypt_ops/digestset.c if USE_NSS @@ -75,5 +75,5 @@ src/lib/crypt_ops/crypto_rsa.h \ src/lib/crypt_ops/crypto_s2k.h \ src/lib/crypt_ops/crypto_sys.h \ - src/lib/crypt_ops/crypto_util.h \ + src/lib/crypt_ops/crypto_util.h \ src/lib/crypt_ops/digestset.h diff -Nru tor-0.4.8.16/src/lib/ctime/include.am tor-0.4.9.6/src/lib/ctime/include.am --- tor-0.4.8.16/src/lib/ctime/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/ctime/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -13,8 +13,8 @@ # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_ctime_a_SOURCES = \ - $(mulodi4_source) \ - src/ext/csiphash.c \ + $(mulodi4_source) \ + src/ext/csiphash.c \ src/lib/ctime/di_ops.c src_lib_libtor_ctime_testing_a_SOURCES = \ diff -Nru tor-0.4.8.16/src/lib/defs/dh_sizes.h tor-0.4.9.6/src/lib/defs/dh_sizes.h --- tor-0.4.8.16/src/lib/defs/dh_sizes.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/defs/dh_sizes.h 2026-03-25 14:30:34.000000000 +0000 @@ -16,7 +16,10 @@ #ifndef TOR_DH_SIZES_H #define TOR_DH_SIZES_H -/** Length of our legacy DH keys. */ +/** Length of our legacy DH keys, in bytes. */ #define DH1024_KEY_LEN (1024/8) +/** Length of our current TLS DH keys, in bytes. */ +#define DH2048_KEY_LEN (2048/8) + #endif /* !defined(TOR_DH_SIZES_H) */ diff -Nru tor-0.4.8.16/src/lib/defs/include.am tor-0.4.9.6/src/lib/defs/include.am --- tor-0.4.8.16/src/lib/defs/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/defs/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -1,8 +1,8 @@ # ADD_C_FILE: INSERT HEADERS HERE. -noinst_HEADERS += \ - src/lib/defs/dh_sizes.h \ +noinst_HEADERS += \ + src/lib/defs/dh_sizes.h \ src/lib/defs/digest_sizes.h \ src/lib/defs/logging_types.h \ - src/lib/defs/time.h \ + src/lib/defs/time.h \ src/lib/defs/x25519_sizes.h diff -Nru tor-0.4.8.16/src/lib/dispatch/dispatch_cfg.c tor-0.4.9.6/src/lib/dispatch/dispatch_cfg.c --- tor-0.4.8.16/src/lib/dispatch/dispatch_cfg.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/dispatch/dispatch_cfg.c 2026-03-25 14:30:34.000000000 +0000 @@ -93,7 +93,7 @@ /** * Associate a receiver with a message ID. Multiple receivers may be - * associated with a single messasge ID. + * associated with a single message ID. * * Return 0 on success, on failure. **/ diff -Nru tor-0.4.8.16/src/lib/dispatch/include.am tor-0.4.9.6/src/lib/dispatch/include.am --- tor-0.4.8.16/src/lib/dispatch/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/dispatch/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -20,8 +20,8 @@ # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ src/lib/dispatch/dispatch.h \ - src/lib/dispatch/dispatch_cfg.h \ - src/lib/dispatch/dispatch_cfg_st.h \ + src/lib/dispatch/dispatch_cfg.h \ + src/lib/dispatch/dispatch_cfg_st.h \ src/lib/dispatch/dispatch_naming.h \ src/lib/dispatch/dispatch_st.h \ src/lib/dispatch/msgtypes.h diff -Nru tor-0.4.8.16/src/lib/err/backtrace.h tor-0.4.9.6/src/lib/err/backtrace.h --- tor-0.4.8.16/src/lib/err/backtrace.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/err/backtrace.h 2026-03-25 14:30:34.000000000 +0000 @@ -29,6 +29,14 @@ #define log_backtrace(sev, dom, msg) \ log_backtrace_impl((sev), (dom), (msg), tor_log) +#define log_backtrace_once(sev, dom, msg) STMT_BEGIN \ + static int backtrace_logged__ = 0; \ + if (!backtrace_logged__) { \ + backtrace_logged__ = 1; \ + log_backtrace((sev), (dom), (msg)); \ + } \ + STMT_END + #ifdef BACKTRACE_PRIVATE #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \ defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION) diff -Nru tor-0.4.8.16/src/lib/evloop/token_bucket.c tor-0.4.9.6/src/lib/evloop/token_bucket.c --- tor-0.4.8.16/src/lib/evloop/token_bucket.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/evloop/token_bucket.c 2026-03-25 14:30:34.000000000 +0000 @@ -58,7 +58,7 @@ } /** - * Adust a preexisting token bucket to respect the new configuration + * Adjust a preexisting token bucket to respect the new configuration * cfg, by decreasing its current level if needed. */ void token_bucket_raw_adjust(token_bucket_raw_t *bucket, diff -Nru tor-0.4.8.16/src/lib/evloop/workqueue.c tor-0.4.9.6/src/lib/evloop/workqueue.c --- tor-0.4.8.16/src/lib/evloop/workqueue.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/evloop/workqueue.c 2026-03-25 14:30:34.000000000 +0000 @@ -38,6 +38,7 @@ #include "lib/net/alertsock.h" #include "lib/net/socket.h" #include "lib/thread/threads.h" +#include "lib/time/compat_time.h" #include "ext/tor_queue.h" #include @@ -78,6 +79,8 @@ /** Number of elements in threads. */ int n_threads; + /** Number of elements to be created in threads. */ + int n_threads_max; /** Mutex to protect all the above fields. */ tor_mutex_t lock; @@ -88,6 +91,11 @@ void *(*new_thread_state_fn)(void*); void (*free_thread_state_fn)(void*); void *new_thread_state_arg; + + /** Used for signalling the worker threads to exit. */ + int exit; + /** Mutex for controlling worker threads' startup and exit. */ + tor_mutex_t control_lock; }; /** Used to put a workqueue_priority_t value into a bitfield. */ @@ -270,13 +278,43 @@ static void worker_thread_main(void *thread_) { + static int n_worker_threads_running = 0; + static unsigned long control_lock_owner = 0; workerthread_t *thread = thread_; threadpool_t *pool = thread->in_pool; workqueue_entry_t *work; workqueue_reply_t result; + tor_mutex_acquire(&pool->control_lock); + log_debug(LD_GENERAL, "Worker thread %u/%u has started [TID: %lu].", + n_worker_threads_running + 1, pool->n_threads_max, + tor_get_thread_id()); + + if (++n_worker_threads_running == pool->n_threads_max) + tor_cond_signal_one(&pool->condition); + + tor_mutex_release(&pool->control_lock); + + /* Wait until all worker threads have started. + * pool->lock must be prelocked here. */ tor_mutex_acquire(&pool->lock); + + if (control_lock_owner == 0) { + /* pool->control_lock stays locked. This is required for the main thread + * to wait for the worker threads to exit on shutdown, so the memory + * clean up won't begin before all threads have exited. */ + tor_mutex_acquire(&pool->control_lock); + control_lock_owner = tor_get_thread_id(); + } + + log_debug(LD_GENERAL, "Worker thread has entered the work loop [TID: %lu].", + tor_get_thread_id()); + while (1) { + /* Exit thread when signaled to exit */ + if (pool->exit) + goto exit; + /* lock must be held at this point. */ while (worker_thread_has_work(thread)) { /* lock must be held at this point. */ @@ -290,11 +328,12 @@ workqueue_reply_t r = update_fn(thread->state, arg); - if (r != WQ_RPL_REPLY) { - return; - } - tor_mutex_acquire(&pool->lock); + + /* We may need to exit the thread. */ + if (r != WQ_RPL_REPLY) + goto exit; + continue; } work = worker_thread_extract_next_work(thread); @@ -309,11 +348,11 @@ /* Queue the reply for the main thread. */ queue_reply(thread->reply_queue, work); - /* We may need to exit the thread. */ - if (result != WQ_RPL_REPLY) { - return; - } tor_mutex_acquire(&pool->lock); + + /* We may need to exit the thread. */ + if (result != WQ_RPL_REPLY) + goto exit; } /* At this point the lock is held, and there is no work in this thread's * queue. */ @@ -325,6 +364,30 @@ log_warn(LD_GENERAL, "Fail tor_cond_wait."); } } + +exit: + /* At this point pool->lock must be held */ + + log_debug(LD_GENERAL, "Worker thread %u/%u has exited [TID: %lu].", + pool->n_threads_max - n_worker_threads_running + 1, + pool->n_threads_max, tor_get_thread_id()); + + if (tor_get_thread_id() == control_lock_owner) { + /* Wait for the other worker threads to exit so we + * can safely unlock pool->control_lock. */ + while (n_worker_threads_running > 1) { + tor_mutex_release(&pool->lock); + tor_sleep_msec(10); + tor_mutex_acquire(&pool->lock); + } + + tor_mutex_release(&pool->lock); + /* Let the main thread know, the last worker thread has exited. */ + tor_mutex_release(&pool->control_lock); + } else { + --n_worker_threads_running; + tor_mutex_release(&pool->lock); + } } /** Put a reply on the reply queue. The reply must not currently be on @@ -516,12 +579,17 @@ if (n > MAX_THREADS) n = MAX_THREADS; + tor_mutex_acquire(&pool->control_lock); tor_mutex_acquire(&pool->lock); if (pool->n_threads < n) pool->threads = tor_reallocarray(pool->threads, sizeof(workerthread_t*), n); + int status = 0; + pool->n_threads_max = n; + log_debug(LD_GENERAL, "Starting worker threads..."); + while (pool->n_threads < n) { /* For half of our threads, we'll choose lower priorities permissively; * for the other half, we'll stick more strictly to higher priorities. @@ -536,16 +604,80 @@ //LCOV_EXCL_START tor_assert_nonfatal_unreached(); pool->free_thread_state_fn(state); - tor_mutex_release(&pool->lock); - return -1; + status = -1; + goto check_status; //LCOV_EXCL_STOP } thr->index = pool->n_threads; pool->threads[pool->n_threads++] = thr; } + + struct timeval tv = {.tv_sec = 30, .tv_usec = 0}; + + /* Wait for the last launched thread to confirm us, it has started. + * Wait max 30 seconds */ + status = tor_cond_wait(&pool->condition, &pool->control_lock, &tv); + +check_status: + switch (status) { + case 0: + log_debug(LD_GENERAL, "Starting worker threads finished."); + break; + case -1: + log_warn(LD_GENERAL, "Failed to confirm worker threads' start up."); + break; + case 1: + log_warn(LD_GENERAL, "Failed to confirm worker threads' " + "start up after timeout."); + FALLTHROUGH; + default: + status = -1; + } + + log_debug(LD_GENERAL, "Signaled the worker threads to enter the work loop."); + + /* If we had an error, let the worker threads (if any) exit directly. */ + if (status != 0) { + pool->exit = 1; + log_debug(LD_GENERAL, "Signaled the worker threads to exit..."); + } + + /* Let worker threads enter the work loop. */ tor_mutex_release(&pool->lock); + /* Let one of the worker threads take the ownership of pool->control_lock. + * This is required for compliance with POSIX. */ + tor_mutex_release(&pool->control_lock); - return 0; + return status; +} + +/** Stop all worker threads */ +static void +threadpool_stop_threads(threadpool_t *pool) +{ + tor_mutex_acquire(&pool->lock); + + if (pool->exit == 0) { + /* Signal the worker threads to exit */ + pool->exit = 1; + /* If worker threads are waiting for work, let them continue to exit */ + tor_cond_signal_all(&pool->condition); + + log_debug(LD_GENERAL, "Signaled worker threads to exit. " + "Waiting for them to exit..."); + } + + tor_mutex_release(&pool->lock); + + /* Wait until all worker threads have exited. + * pool->control_lock must be prelocked here. */ + tor_mutex_acquire(&pool->control_lock); + /* Unlock required, else main thread hangs on mutex uninit. */ + tor_mutex_release(&pool->control_lock); + + /* If this message appears in the log before all threads have confirmed + * their exit, then pool->control_lock wasn't prelocked for some reason. */ + log_debug(LD_GENERAL, "All worker threads have exited."); } /** @@ -566,6 +698,9 @@ pool = tor_malloc_zero(sizeof(threadpool_t)); tor_mutex_init_nonrecursive(&pool->lock); tor_cond_init(&pool->condition); + tor_mutex_init_nonrecursive(&pool->control_lock); + pool->exit = 0; + unsigned i; for (i = WORKQUEUE_PRIORITY_FIRST; i <= WORKQUEUE_PRIORITY_LAST; ++i) { TOR_TAILQ_INIT(&pool->work[i]); @@ -579,8 +714,6 @@ if (threadpool_start_threads(pool, n_threads) < 0) { //LCOV_EXCL_START tor_assert_nonfatal_unreached(); - tor_cond_uninit(&pool->condition); - tor_mutex_uninit(&pool->lock); threadpool_free(pool); return NULL; //LCOV_EXCL_STOP @@ -598,6 +731,14 @@ if (!pool) return; + threadpool_stop_threads(pool); + + log_debug(LD_GENERAL, "Beginning to clean up..."); + + tor_cond_uninit(&pool->condition); + tor_mutex_uninit(&pool->lock); + tor_mutex_uninit(&pool->control_lock); + if (pool->threads) { for (int i = 0; i != pool->n_threads; ++i) workerthread_free(pool->threads[i]); @@ -605,21 +746,35 @@ tor_free(pool->threads); } - if (pool->update_args) - pool->free_update_arg_fn(pool->update_args); + if (pool->update_args) { + if (!pool->free_update_arg_fn) + log_warn(LD_GENERAL, "Freeing pool->update_args not possible. " + "pool->free_update_arg_fn is not set."); + else + pool->free_update_arg_fn(pool->update_args); + } if (pool->reply_event) { - tor_event_del(pool->reply_event); - tor_event_free(pool->reply_event); + if (tor_event_del(pool->reply_event) == -1) + log_warn(LD_GENERAL, "libevent error: deleting reply event failed."); + else + tor_event_free(pool->reply_event); } if (pool->reply_queue) replyqueue_free(pool->reply_queue); - if (pool->new_thread_state_arg) - pool->free_thread_state_fn(pool->new_thread_state_arg); + if (pool->new_thread_state_arg) { + if (!pool->free_thread_state_fn) + log_warn(LD_GENERAL, "Freeing pool->new_thread_state_arg not possible. " + "pool->free_thread_state_fn is not set."); + else + pool->free_thread_state_fn(pool->new_thread_state_arg); + } tor_free(pool); + + log_debug(LD_GENERAL, "Cleanup finished."); } /** Return the reply queue associated with a given thread pool. */ diff -Nru tor-0.4.8.16/src/lib/fdio/fdio.c tor-0.4.9.6/src/lib/fdio/fdio.c --- tor-0.4.8.16/src/lib/fdio/fdio.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/fdio/fdio.c 2026-03-25 14:30:34.000000000 +0000 @@ -14,6 +14,9 @@ #ifdef HAVE_UNISTD_H #include #endif +#ifdef HAVE_FCNTL_H +#include +#endif #ifdef _WIN32 #include #endif @@ -118,3 +121,28 @@ } return 0; } + +#if defined(HAVE_PIPE2) && defined(O_CLOEXEC) +int +tor_pipe_cloexec(int pipefd[2]) +{ + return pipe2(pipefd, O_CLOEXEC); +} +#elif defined(HAVE_PIPE) && defined(FD_CLOEXEC) +int +tor_pipe_cloexec(int pipefd[2]) +{ + if (pipe(pipefd)) { + return -1; + } + if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC)) { + return -1; + } + if (fcntl(pipefd[1], F_SETFD, FD_CLOEXEC)) { + return -1; + } + return 0; +} +#else +/* Intentionally leave symbol undefined. */ +#endif diff -Nru tor-0.4.8.16/src/lib/fdio/fdio.h tor-0.4.9.6/src/lib/fdio/fdio.h --- tor-0.4.8.16/src/lib/fdio/fdio.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/fdio/fdio.h 2026-03-25 14:30:34.000000000 +0000 @@ -22,5 +22,6 @@ int tor_fd_seekend(int fd); int tor_ftruncate(int fd); int write_all_to_fd_minimal(int fd, const char *buf, size_t count); +int tor_pipe_cloexec(int pipefd[2]); #endif /* !defined(TOR_FDIO_H) */ diff -Nru tor-0.4.8.16/src/lib/fdio/include.am tor-0.4.9.6/src/lib/fdio/include.am --- tor-0.4.8.16/src/lib/fdio/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/fdio/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -15,5 +15,5 @@ src_lib_libtor_fdio_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) # ADD_C_FILE: INSERT HEADERS HERE. -noinst_HEADERS += \ +noinst_HEADERS += \ src/lib/fdio/fdio.h diff -Nru tor-0.4.8.16/src/lib/fs/conffile.c tor-0.4.9.6/src/lib/fs/conffile.c --- tor-0.4.8.16/src/lib/fs/conffile.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/fs/conffile.c 2026-03-25 14:30:34.000000000 +0000 @@ -54,7 +54,7 @@ opened_lst, 1, NULL, config_process_include); } -/** Return a list of paths obtained when expading globs in pattern. +/** Return a list of paths obtained when expanding globs in pattern. * If pattern has no globs, return a list with pattern in it. * If opened_files is provided, add paths opened by glob to it. * Return NULL on failure. */ diff -Nru tor-0.4.8.16/src/lib/fs/files.c tor-0.4.9.6/src/lib/fs/files.c --- tor-0.4.8.16/src/lib/fs/files.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/fs/files.c 2026-03-25 14:30:34.000000000 +0000 @@ -573,9 +573,10 @@ /** * Read the contents of the open file fd presuming it is a FIFO * (or similar) file descriptor for which the size of the file isn't - * known ahead of time. Return NULL on failure, and a NUL-terminated - * string on success. On success, set sz_out to the number of - * bytes read. + * known ahead of time. + * Return NULL on failure, and a NUL-terminated string on success. + * On success, set sz_out to the number of bytes read (not including + * the final NULL, which wasn't read from fd). */ char * read_file_to_str_until_eof(int fd, size_t max_bytes_to_read, size_t *sz_out) diff -Nru tor-0.4.8.16/src/lib/fs/files.h tor-0.4.9.6/src/lib/fs/files.h --- tor-0.4.8.16/src/lib/fs/files.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/fs/files.h 2026-03-25 14:30:34.000000000 +0000 @@ -29,6 +29,10 @@ #endif #endif /* defined(_WIN32) */ +#if HAVE_FCNTL_H +#include +#endif + #ifndef O_BINARY #define O_BINARY 0 #endif diff -Nru tor-0.4.8.16/src/lib/fs/path.c tor-0.4.9.6/src/lib/fs/path.c --- tor-0.4.8.16/src/lib/fs/path.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/fs/path.c 2026-03-25 14:30:34.000000000 +0000 @@ -108,7 +108,8 @@ rest = strlen(filename)>=2?(filename+2):""; } else { #ifdef HAVE_PWD_H - char *username, *slash; + char *username; + const char *slash; slash = strchr(filename, '/'); if (slash) username = tor_strndup(filename+1,slash-filename-1); diff -Nru tor-0.4.8.16/src/lib/geoip/include.am tor-0.4.9.6/src/lib/geoip/include.am --- tor-0.4.8.16/src/lib/geoip/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/geoip/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -15,5 +15,5 @@ # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ - src/lib/geoip/geoip.h \ + src/lib/geoip/geoip.h \ src/lib/geoip/country.h diff -Nru tor-0.4.8.16/src/lib/lock/include.am tor-0.4.9.6/src/lib/lock/include.am --- tor-0.4.8.16/src/lib/lock/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/lock/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -22,5 +22,5 @@ src_lib_libtor_lock_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) # ADD_C_FILE: INSERT HEADERS HERE. -noinst_HEADERS += \ +noinst_HEADERS += \ src/lib/lock/compat_mutex.h diff -Nru tor-0.4.8.16/src/lib/log/log.c tor-0.4.9.6/src/lib/log/log.c --- tor-0.4.8.16/src/lib/log/log.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/log/log.c 2026-03-25 14:30:34.000000000 +0000 @@ -33,6 +33,7 @@ #define LOG_PRIVATE #include "lib/log/log.h" #include "lib/log/log_sys.h" +#include "lib/log/util_bug.h" #include "lib/version/git_revision.h" #include "lib/log/ratelim.h" #include "lib/lock/compat_mutex.h" @@ -706,6 +707,8 @@ const char *format, ...) { va_list ap; + if ((domain & LD_BUG) && (severity >= LOG_WARN)) + tor_bug_increment_count_(); if (severity > log_global_min_severity_) return; va_start(ap,format); @@ -718,6 +721,8 @@ { va_list ap; char *m; + if ((domain & LD_BUG) && (severity >= LOG_WARN)) + tor_bug_increment_count_(); if (severity > log_global_min_severity_) return; m = rate_limit_log(ratelim, approx_time()); @@ -912,6 +917,7 @@ { if (!log_mutex_initialized) { tor_mutex_init(&log_mutex); + tor_bug_init_counter(); log_mutex_initialized = 1; } #ifdef __GNUC__ diff -Nru tor-0.4.8.16/src/lib/log/log_sys.c tor-0.4.9.6/src/lib/log/log_sys.c --- tor-0.4.8.16/src/lib/log/log_sys.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/log/log_sys.c 2026-03-25 14:30:34.000000000 +0000 @@ -11,11 +11,16 @@ #include "lib/log/escape.h" #include "lib/log/log.h" #include "lib/log/log_sys.h" +#include "lib/log/util_bug.h" +#include "lib/metrics/metrics_store.h" + +static metrics_store_t *the_store; static int subsys_logging_initialize(void) { init_logging(0); + the_store = metrics_store_new(); return 0; } @@ -26,6 +31,29 @@ escaped(NULL); } +static const smartlist_t * +logging_metrics_get_stores(void) +{ + static smartlist_t *stores_list = NULL; + + metrics_store_reset(the_store); + + metrics_store_entry_t *sentry = metrics_store_add( + the_store, + METRICS_TYPE_COUNTER, + METRICS_NAME(bug_reached_count), + "Total number of BUG() and similar assertion reached", + 0, NULL); + metrics_store_entry_update(sentry, tor_bug_get_count()); + + if (!stores_list) { + stores_list = smartlist_new(); + smartlist_add(stores_list, the_store); + } + + return stores_list; +} + const subsys_fns_t sys_logging = { .name = "log", SUBSYS_DECLARE_LOCATION(), @@ -35,4 +63,5 @@ .level = -90, .initialize = subsys_logging_initialize, .shutdown = subsys_logging_shutdown, + .get_metrics = logging_metrics_get_stores, }; diff -Nru tor-0.4.8.16/src/lib/log/util_bug.c tor-0.4.9.6/src/lib/log/util_bug.c --- tor-0.4.8.16/src/lib/log/util_bug.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/log/util_bug.c 2026-03-25 14:30:34.000000000 +0000 @@ -18,6 +18,7 @@ #endif #include "lib/malloc/malloc.h" #include "lib/string/printf.h" +#include "lib/thread/threads.h" #include #include @@ -101,6 +102,27 @@ tor_free(buf); } +static atomic_counter_t total_bug_reached; + +void +tor_bug_init_counter(void) +{ + atomic_counter_init(&total_bug_reached); +} + +/** Helper to update BUG count in metrics. */ +void +tor_bug_increment_count_(void) +{ + atomic_counter_add(&total_bug_reached, 1); +} + +size_t +tor_bug_get_count(void) +{ + return atomic_counter_get(&total_bug_reached); +} + /** Helper for tor_assert_nonfatal: report the assertion failure. */ void tor_bug_occurred_(const char *fname, unsigned int line, @@ -110,6 +132,11 @@ char *buf = NULL; const char *once_str = once ? " (Future instances of this warning will be silenced.)": ""; + if (! once) { + // _once assertions count from the macro directly so we count them as many + // times as they are reached, and not just once. + tor_bug_increment_count_(); + } if (! expr) { if (capturing_bugs()) { add_captured_bug("This line should not have been reached."); diff -Nru tor-0.4.8.16/src/lib/log/util_bug.h tor-0.4.9.6/src/lib/log/util_bug.h --- tor-0.4.8.16/src/lib/log/util_bug.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/log/util_bug.h 2026-03-25 14:30:34.000000000 +0000 @@ -39,6 +39,7 @@ #include "orconfig.h" #include "lib/cc/compat_compiler.h" #include "lib/log/log.h" +#include "lib/smartlist_core/smartlist_core.h" #include "lib/testsupport/testsupport.h" /* Replace assert() with a variant that sends failures to the log before @@ -191,6 +192,7 @@ STMT_END #define tor_assert_nonfatal_unreached_once() STMT_BEGIN \ static int warning_logged__ = 0; \ + tor_bug_increment_count_(); \ if (!warning_logged__) { \ warning_logged__ = 1; \ tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, NULL, 1, NULL); \ @@ -198,10 +200,12 @@ STMT_END #define tor_assert_nonfatal_once(cond) STMT_BEGIN \ static int warning_logged__ = 0; \ - if (ASSERT_PREDICT_LIKELY_(cond)) { \ - } else if (!warning_logged__) { \ - warning_logged__ = 1; \ - tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 1, NULL);\ + if (!ASSERT_PREDICT_LIKELY_(cond)) { \ + tor_bug_increment_count_(); \ + if (!warning_logged__) { \ + warning_logged__ = 1; \ + tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, #cond, 1, NULL);\ + } \ } \ STMT_END #define BUG(cond) \ @@ -215,18 +219,22 @@ if (( { \ static int var = 0; \ int bool_result = !!(cond); \ - if (bool_result && !var) { \ - var = 1; \ - tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \ - ("!("#cond")"), 1, NULL); \ + if (bool_result) { \ + tor_bug_increment_count_(); \ + if (!var) { \ + var = 1; \ + tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \ + ("!("#cond")"), 1, NULL); \ + } \ } \ bool_result; } )) #else /* !defined(__GNUC__) */ #define IF_BUG_ONCE__(cond,var) \ static int var = 0; \ if ((cond) ? \ - (var ? 1 : \ + (var ? (tor_bug_increment_count_(), 1) : \ (var=1, \ + tor_bug_increment_count_(), \ tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \ ("!("#cond")"), 1, NULL), \ 1)) \ @@ -273,12 +281,15 @@ const char *func, const char *expr, const char *fmt, ...) CHECK_PRINTF(5,6); +void tor_bug_increment_count_(void); +size_t tor_bug_get_count(void); void tor_bug_occurred_(const char *fname, unsigned int line, const char *func, const char *expr, int once, const char *fmt, ...) CHECK_PRINTF(6,7); void tor_abort_(void) ATTR_NORETURN; +void tor_bug_init_counter(void); #ifdef _WIN32 #define SHORT_FILE__ (tor_fix_source_file(__FILE__)) diff -Nru tor-0.4.8.16/src/lib/math/include.am tor-0.4.9.6/src/lib/math/include.am --- tor-0.4.8.16/src/lib/math/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/math/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -7,7 +7,7 @@ # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_math_a_SOURCES = \ - src/lib/math/fp.c \ + src/lib/math/fp.c \ src/lib/math/laplace.c \ src/lib/math/prob_distr.c @@ -19,6 +19,6 @@ # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ src/lib/math/fp.h \ - src/lib/math/laplace.h \ - src/lib/math/prob_distr.h \ + src/lib/math/laplace.h \ + src/lib/math/prob_distr.h \ src/lib/math/stats.h diff -Nru tor-0.4.8.16/src/lib/metrics/include.am tor-0.4.9.6/src/lib/metrics/include.am --- tor-0.4.8.16/src/lib/metrics/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/metrics/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -8,8 +8,8 @@ # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_metrics_a_SOURCES = \ src/lib/metrics/metrics_store.c \ - src/lib/metrics/metrics_store_entry.c \ - src/lib/metrics/metrics_common.c \ + src/lib/metrics/metrics_store_entry.c \ + src/lib/metrics/metrics_common.c \ src/lib/metrics/prometheus.c src_lib_libtor_metrics_testing_a_SOURCES = \ @@ -18,8 +18,8 @@ src_lib_libtor_metrics_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) # ADD_C_FILE: INSERT HEADERS HERE. -noinst_HEADERS += \ - src/lib/metrics/metrics_store.h \ +noinst_HEADERS += \ + src/lib/metrics/metrics_store.h \ src/lib/metrics/metrics_store_entry.h \ src/lib/metrics/metrics_common.h \ src/lib/metrics/prometheus.h diff -Nru tor-0.4.8.16/src/lib/net/include.am tor-0.4.9.6/src/lib/net/include.am --- tor-0.4.8.16/src/lib/net/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/net/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -8,7 +8,7 @@ # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_net_a_SOURCES = \ src/lib/net/address.c \ - src/lib/net/alertsock.c \ + src/lib/net/alertsock.c \ src/lib/net/buffers_net.c \ src/lib/net/gethostname.c \ src/lib/net/inaddr.c \ @@ -25,7 +25,7 @@ # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ src/lib/net/address.h \ - src/lib/net/alertsock.h \ + src/lib/net/alertsock.h \ src/lib/net/buffers_net.h \ src/lib/net/gethostname.h \ src/lib/net/inaddr.h \ diff -Nru tor-0.4.8.16/src/lib/net/socket.c tor-0.4.9.6/src/lib/net/socket.c --- tor-0.4.8.16/src/lib/net/socket.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/net/socket.c 2026-03-25 14:30:34.000000000 +0000 @@ -652,7 +652,13 @@ #if defined(_WIN32) #define E(code, s) { code, (s " [" #code " ]") } -struct { int code; const char *msg; } windows_socket_errors[] = { + +typedef struct windows_socket_error { + int code; + const char *msg; +} windows_socket_error_t; + +static windows_socket_error_t windows_socket_errors[] = { E(WSAEINTR, "Interrupted function call"), E(WSAEACCES, "Permission denied"), E(WSAEFAULT, "Bad address"), diff -Nru tor-0.4.8.16/src/lib/osinfo/include.am tor-0.4.9.6/src/lib/osinfo/include.am --- tor-0.4.8.16/src/lib/osinfo/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/osinfo/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -6,7 +6,7 @@ endif # ADD_C_FILE: INSERT SOURCES HERE. -src_lib_libtor_osinfo_a_SOURCES = \ +src_lib_libtor_osinfo_a_SOURCES = \ src/lib/osinfo/uname.c \ src/lib/osinfo/libc.c @@ -16,6 +16,6 @@ src_lib_libtor_osinfo_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) # ADD_C_FILE: INSERT HEADERS HERE. -noinst_HEADERS += \ +noinst_HEADERS += \ src/lib/osinfo/uname.h \ src/lib/osinfo/libc.h diff -Nru tor-0.4.8.16/src/lib/process/daemon.c tor-0.4.9.6/src/lib/process/daemon.c --- tor-0.4.8.16/src/lib/process/daemon.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/process/daemon.c 2026-03-25 14:30:34.000000000 +0000 @@ -13,6 +13,7 @@ #ifndef _WIN32 +#include "lib/fdio/fdio.h" #include "lib/fs/files.h" #include "lib/log/log.h" #include "lib/thread/threads.h" @@ -63,7 +64,7 @@ return 0; start_daemon_called = 1; - if (pipe(daemon_filedes)) { + if (tor_pipe_cloexec(daemon_filedes)) { /* LCOV_EXCL_START */ log_err(LD_GENERAL,"pipe failed; exiting. Error was %s", strerror(errno)); exit(1); // exit ok: during daemonize, pipe failed. diff -Nru tor-0.4.8.16/src/lib/process/process_unix.c tor-0.4.9.6/src/lib/process/process_unix.c --- tor-0.4.8.16/src/lib/process/process_unix.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/process/process_unix.c 2026-03-25 14:30:34.000000000 +0000 @@ -49,8 +49,7 @@ #ifndef _WIN32 -/** Maximum number of file descriptors, if we cannot get it via sysconf() */ -#define DEFAULT_MAX_FD 256 +#include "lib/fdio/fdio.h" /** Internal state for Unix handles. */ struct process_unix_handle_t { @@ -130,19 +129,17 @@ process_status_t process_unix_exec(process_t *process) { - static int max_fd = -1; - process_unix_t *unix_process; pid_t pid; int stdin_pipe[2]; int stdout_pipe[2]; int stderr_pipe[2]; - int retval, fd; + int retval; unix_process = process_get_unix_process(process); /* Create standard in pipe. */ - retval = pipe(stdin_pipe); + retval = tor_pipe_cloexec(stdin_pipe); if (-1 == retval) { log_warn(LD_PROCESS, @@ -154,7 +151,7 @@ } /* Create standard out pipe. */ - retval = pipe(stdout_pipe); + retval = tor_pipe_cloexec(stdout_pipe); if (-1 == retval) { log_warn(LD_PROCESS, @@ -170,7 +167,7 @@ } /* Create standard error pipe. */ - retval = pipe(stderr_pipe); + retval = tor_pipe_cloexec(stderr_pipe); if (-1 == retval) { log_warn(LD_PROCESS, @@ -189,20 +186,6 @@ return PROCESS_STATUS_ERROR; } -#ifdef _SC_OPEN_MAX - if (-1 == max_fd) { - max_fd = (int)sysconf(_SC_OPEN_MAX); - - if (max_fd == -1) { - max_fd = DEFAULT_MAX_FD; - log_warn(LD_PROCESS, - "Cannot find maximum file descriptor, assuming: %d", max_fd); - } - } -#else /* !defined(_SC_OPEN_MAX) */ - max_fd = DEFAULT_MAX_FD; -#endif /* defined(_SC_OPEN_MAX) */ - pid = fork(); if (0 == pid) { @@ -240,11 +223,9 @@ close(stdin_pipe[0]); close(stdin_pipe[1]); - /* Close all other fds, including the read end of the pipe. XXX: We should - * now be doing enough FD_CLOEXEC setting to make this needless. - */ - for (fd = STDERR_FILENO + 1; fd < max_fd; fd++) - close(fd); + /* Note that we don't close all FDs from here, which we used to do, because + * all our open are CLOEXEC. With a very large maximum number of FDs, the + * loop was taking a long time: #40990 */ /* Create the argv value for our new process. */ char **argv = process_get_argv(process); diff -Nru tor-0.4.8.16/src/lib/process/restrict.c tor-0.4.9.6/src/lib/process/restrict.c --- tor-0.4.8.16/src/lib/process/restrict.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/process/restrict.c 2026-03-25 14:30:34.000000000 +0000 @@ -177,8 +177,8 @@ * return 0 and max_out is set to the current maximum value returned * by getrlimit(). * - * Otherwise, return 0 and store the maximum we found inside max_out - * and set max_sockets with that value as well.*/ + * Otherwise: return 0, store the maximum we found inside max_out, + * and call set_max_sockets() with that value as well.*/ int set_max_file_descriptors(rlim_t limit, int *max_out) { diff -Nru tor-0.4.8.16/src/lib/process/waitpid.c tor-0.4.9.6/src/lib/process/waitpid.c --- tor-0.4.8.16/src/lib/process/waitpid.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/process/waitpid.c 2026-03-25 14:30:34.000000000 +0000 @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2021, The Tor Project, Inc. */ + * Copyright (c) 2007-2025, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -146,6 +146,7 @@ int status = 0; while ((child = waitpid(-1, &status, WNOHANG)) > 0) { + status = WIFEXITED(status) ? WEXITSTATUS(status) : -1; notify_waitpid_callback_by_pid(child, status); status = 0; /* should be needless */ } diff -Nru tor-0.4.8.16/src/lib/sandbox/sandbox.c tor-0.4.9.6/src/lib/sandbox/sandbox.c --- tor-0.4.8.16/src/lib/sandbox/sandbox.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/sandbox/sandbox.c 2026-03-25 14:30:34.000000000 +0000 @@ -23,7 +23,7 @@ * * 28/06/2017: This value was increased from 16 MB to 20 MB after we introduced * LZMA support in Tor (0.3.1.1-alpha). We limit our LZMA coder to 16 MB, but - * liblzma have a small overhead that we need to compensate for to avoid being + * liblzma has a small overhead that we need to compensate for to avoid being * killed by the sandbox. */ #define MALLOC_MP_LIM (20*1024*1024) @@ -125,6 +125,15 @@ #define SYSCALL_NAME_DEBUGGING #endif +/** + * On newer architectures Linux provides a standardized, generic set of system + * calls (defined in Linux's include/uapi/asm-generic/unistd.h), which omits a + * number of legacy calls used by glibc on other platforms. + */ +#if defined(__aarch64__) || defined(__riscv) +#define ARCH_USES_GENERIC_SYSCALLS +#endif + /**Determines if at least one sandbox is active.*/ static int sandbox_active = 0; /** Holds the parameter list configuration for the sandbox.*/ @@ -263,8 +272,9 @@ #ifdef __NR_sigreturn SCMP_SYS(sigreturn), #endif +#if defined(__NR_stat) SCMP_SYS(stat), -#if defined(__i386__) && defined(__NR_statx) +#elif defined(__i386__) && defined(__NR_statx) SCMP_SYS(statx), #endif SCMP_SYS(uname), @@ -279,6 +289,10 @@ // getaddrinfo uses this.. SCMP_SYS(stat64), #endif +#ifdef __NR_lstat64 + // glob uses this on i386 with glibc 2.36+ + SCMP_SYS(lstat64), +#endif #ifdef __NR_getrandom SCMP_SYS(getrandom), @@ -318,7 +332,7 @@ }; /* opendir is not a syscall but it will use either open or openat. We do not - * want the decision to allow open/openat to be the callers reponsability, so + * want the decision to allow open/openat to be the callers responsibility, so * we create a phony syscall number for opendir and sb_opendir will choose the * correct syscall. */ #define PHONY_OPENDIR_SYSCALL -2 @@ -335,6 +349,8 @@ seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3)) #define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \ seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4)) +#define seccomp_rule_add_5(ctx,act,call,f1,f2,f3,f4,f5) \ + seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4),(f5)) static const char *sandbox_get_interned_string(const char *str); @@ -516,18 +532,33 @@ static int libc_uses_openat_for_open(void) { +#ifdef __NR_open return is_libc_at_least(2, 26); +#else + return 1; +#endif /* defined(__NR_open) */ } +/* Calls to opendir() cannot be filtered by the sandbox when built with fragile + * hardening for an architecture that uses Linux's generic syscall interface, + * so prevent a compiler warning by omitting this function along with + * sb_opendir(). */ +#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS)) /* Return true if we think we're running with a libc that uses openat for the * opendir function on linux. */ static int libc_uses_openat_for_opendir(void) { +#ifdef __NR_open // libc 2.27 and above or between 2.15 (inclusive) and 2.22 (exclusive) return is_libc_at_least(2, 27) || (is_libc_at_least(2, 15) && !is_libc_at_least(2, 22)); +#else + return 1; +#endif /* defined(__NR_open) */ } +#endif /* !(defined(ENABLE_FRAGILE_HARDENING) && + defined(ARCH_USES_GENERIC_SYSCALLS)) */ /** Allow a single file to be opened. If use_openat is true, * we're using a libc that remaps all the opens into openats. */ @@ -557,10 +588,25 @@ int use_openat = libc_uses_openat_for_open(); #ifdef ENABLE_FRAGILE_HARDENING - /* AddressSanitizer uses the "open" syscall to access information about the - * running process via the filesystem, so that call must be allowed without + /* AddressSanitizer uses either the "open" or the "openat" syscall (depending + * on the architecture) to access information about the running process via + * the filesystem, so the appropriate call must be allowed without * restriction or the sanitizer will be unable to execute normally when the * process terminates. */ +#ifdef ARCH_USES_GENERIC_SYSCALLS + rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), + SCMP_CMP_LOWER32_EQ(0, AT_FDCWD)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received " + "libseccomp error %d", rc); + return rc; + } + + /* The "open" syscall is not defined on this architecture, so any other + * requests to open files will necessarily use "openat" as well and there is + * no need to consider any additional rules. */ + return 0; +#else rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " @@ -572,7 +618,8 @@ * there is no need to consider any additional rules. */ if (!use_openat) return 0; -#endif +#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) */ +#endif /* defined(ENABLE_FRAGILE_HARDENING) */ // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { @@ -592,6 +639,33 @@ return 0; } +#ifdef ARCH_USES_GENERIC_SYSCALLS +static int +sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +{ + int rc; + sandbox_cfg_t *elem = NULL; + + // for each dynamic parameter filters + for (elem = filter; elem != NULL; elem = elem->next) { + smp_param_t *param = elem->param; + + if (param != NULL && param->prot == 1 && param->syscall + == SCMP_SYS(fchmodat)) { + rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmodat), + SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), + SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add fchmodat syscall, received " + "libseccomp error %d", rc); + return rc; + } + } + } + + return 0; +} +#else static int sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -616,9 +690,11 @@ return 0; } +#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) */ +#if defined(ARCH_USES_GENERIC_SYSCALLS) static int -sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; sandbox_cfg_t *elem = NULL; @@ -628,12 +704,12 @@ smp_param_t *param = elem->param; if (param != NULL && param->prot == 1 && param->syscall - == SCMP_SYS(fchmodat)) { - rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmodat), + == SCMP_SYS(fchownat)) { + rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchownat), SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value)); if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add fchmodat syscall, received " + log_err(LD_BUG,"(Sandbox) failed to add fchownat syscall, received " "libseccomp error %d", rc); return rc; } @@ -642,8 +718,7 @@ return 0; } - -#ifdef __i386__ +#elif defined(__i386__) static int sb_chown32(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -693,10 +768,15 @@ return 0; } -#endif /* defined(__i386__) */ +#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) || defined(__i386__) */ +#if defined(__NR_rename) +/** + * Function responsible for setting up the rename syscall for + * the seccomp filter sandbox. + */ static int -sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; sandbox_cfg_t *elem = NULL; @@ -705,13 +785,14 @@ for (elem = filter; elem != NULL; elem = elem->next) { smp_param_t *param = elem->param; - if (param != NULL && param->prot == 1 && param->syscall - == SCMP_SYS(fchownat)) { - rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchownat), - SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), - SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value)); + if (param != NULL && param->prot == 1 && + param->syscall == SCMP_SYS(rename)) { + + rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename), + SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value), + SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2)); if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add fchownat syscall, received " + log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received " "libseccomp error %d", rc); return rc; } @@ -720,13 +801,13 @@ return 0; } - +#elif defined(__NR_renameat) /** - * Function responsible for setting up the rename syscall for + * Function responsible for setting up the renameat syscall for * the seccomp filter sandbox. */ static int -sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; sandbox_cfg_t *elem = NULL; @@ -736,13 +817,15 @@ smp_param_t *param = elem->param; if (param != NULL && param->prot == 1 && - param->syscall == SCMP_SYS(rename)) { + param->syscall == SCMP_SYS(renameat)) { - rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename), - SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value), - SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2)); + rc = seccomp_rule_add_4(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat), + SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), + SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value), + SCMP_CMP_LOWER32_EQ(2, AT_FDCWD), + SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2)); if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received " + log_err(LD_BUG,"(Sandbox) failed to add renameat syscall, received " "libseccomp error %d", rc); return rc; } @@ -751,13 +834,13 @@ return 0; } - +#else /** - * Function responsible for setting up the renameat syscall for + * Function responsible for setting up the renameat2 syscall for * the seccomp filter sandbox. */ static int -sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +sb_renameat2(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; sandbox_cfg_t *elem = NULL; @@ -767,15 +850,16 @@ smp_param_t *param = elem->param; if (param != NULL && param->prot == 1 && - param->syscall == SCMP_SYS(renameat)) { + param->syscall == SCMP_SYS(renameat2)) { - rc = seccomp_rule_add_4(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat), + rc = seccomp_rule_add_5(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat2), SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value), SCMP_CMP_LOWER32_EQ(2, AT_FDCWD), - SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2)); + SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2), + SCMP_CMP(4, SCMP_CMP_EQ, 0)); if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add renameat syscall, received " + log_err(LD_BUG,"(Sandbox) failed to add renameat2 syscall, received " "libseccomp error %d", rc); return rc; } @@ -784,7 +868,19 @@ return 0; } +#endif /* defined(__NR_rename) || defined(__NR_renameat) */ +/* If Tor is built with fragile hardening for an architecture that uses Linux's + * generic syscall interface a rule allowing the "openat" syscall without + * restriction will have already been added by sb_open(), so there is no need + * to consider adding additional, more restrictive rules here as they will + * simply be ignored. + * + * Also, since the "open" syscall is not defined on these architectures, glibc + * will necessarily use "openat" for its implementation of opendir() as well. + * This means neither of the following two functions will have any effect and + * both can be omitted. */ +#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS)) /** * Function responsible for setting up the openat syscall for * the seccomp filter sandbox. @@ -840,6 +936,8 @@ return 0; } +#endif /* !(defined(ENABLE_FRAGILE_HARDENING) && + defined(ARCH_USES_GENERIC_SYSCALLS)) */ #ifdef ENABLE_FRAGILE_HARDENING /** @@ -859,9 +957,17 @@ if (rc) return rc; + /* AddressSanitizer uses "PTRACE_GETREGSET" on AArch64 (ARM64) and + * System/390, "PTRACE_GETREGS" everywhere else. */ +#if defined(__aarch64__) || defined(__s390__) + rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace), + SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_GETREGSET), + SCMP_CMP(1, SCMP_CMP_EQ, pid)); +#else rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace), SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_GETREGS), SCMP_CMP(1, SCMP_CMP_EQ, pid)); +#endif /* defined(__aarch64__) || defined(__s390__) */ if (rc) return rc; @@ -1351,6 +1457,40 @@ return 0; } +#ifdef ARCH_USES_GENERIC_SYSCALLS +/** + * Function responsible for setting up the newfstatat syscall for + * the seccomp filter sandbox. + */ +static int +sb_newfstatat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +{ + int rc = 0; + + sandbox_cfg_t *elem = NULL; + + // for each dynamic parameter filters + for (elem = filter; elem != NULL; elem = elem->next) { + smp_param_t *param = elem->param; + + if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open) + || param->syscall == PHONY_OPENDIR_SYSCALL + || param->syscall == SCMP_SYS(newfstatat))) { + rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat), + SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), + SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add newfstatat syscall, received " + "libseccomp error %d", rc); + return rc; + } + } + } + + return 0; +} +#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) */ + #ifdef __NR_stat64 /** * Function responsible for setting up the stat64 syscall for @@ -1409,22 +1549,33 @@ #ifdef __NR_mmap2 sb_mmap2, #endif -#ifdef __i386__ +#if defined(ARCH_USES_GENERIC_SYSCALLS) + sb_fchownat, +#elif defined(__i386__) sb_chown32, #else sb_chown, #endif - sb_fchownat, - sb_chmod, +#if defined(ARCH_USES_GENERIC_SYSCALLS) sb_fchmodat, +#else + sb_chmod, +#endif sb_open, +#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS)) sb_openat, sb_opendir, +#endif #ifdef ENABLE_FRAGILE_HARDENING sb_ptrace, #endif +#if defined(__NR_rename) sb_rename, +#elif defined(__NR_renameat) sb_renameat, +#else + sb_renameat2, +#endif #ifdef __NR_fcntl64 sb_fcntl64, #endif @@ -1434,7 +1585,9 @@ sb_flock, sb_futex, sb_mremap, -#ifdef __NR_stat64 +#if defined(ARCH_USES_GENERIC_SYSCALLS) + sb_newfstatat, +#elif defined(__NR_stat64) sb_stat64, #endif @@ -1690,27 +1843,31 @@ return new_element2(syscall, value, NULL); } -#ifdef __i386__ -#define SCMP_chown SCMP_SYS(chown32) -#elif defined(__aarch64__) && defined(__LP64__) +#if defined(ARCH_USES_GENERIC_SYSCALLS) #define SCMP_chown SCMP_SYS(fchownat) +#elif defined(__i386__) +#define SCMP_chown SCMP_SYS(chown32) #else #define SCMP_chown SCMP_SYS(chown) #endif -#if defined(__aarch64__) && defined(__LP64__) +#if defined(ARCH_USES_GENERIC_SYSCALLS) #define SCMP_chmod SCMP_SYS(fchmodat) #else #define SCMP_chmod SCMP_SYS(chmod) #endif -#if defined(__aarch64__) && defined(__LP64__) +#if defined(__NR_rename) +#define SCMP_rename SCMP_SYS(rename) +#elif defined(__NR_renameat) #define SCMP_rename SCMP_SYS(renameat) #else -#define SCMP_rename SCMP_SYS(rename) +#define SCMP_rename SCMP_SYS(renameat2) #endif -#ifdef __NR_stat64 +#if defined(ARCH_USES_GENERIC_SYSCALLS) +#define SCMP_stat SCMP_SYS(newfstatat) +#elif defined(__NR_stat64) #define SCMP_stat SCMP_SYS(stat64) #else #define SCMP_stat SCMP_SYS(stat) @@ -1869,6 +2026,25 @@ "received libseccomp error %d", rc); return rc; } +#elif defined(__NR_fstatat64) + // On i386, glibc uses fstatat64 instead of newfstatat. + // This is needed for glob() and stat() operations on 32-bit systems. + rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstatat64)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add fstatat64() syscall; " + "received libseccomp error %d", rc); + return rc; + } +#endif +#if defined(__i386__) && defined(__NR_statx) + // On i386 with glibc 2.33+, statx may be used for time64 support. + // glob() in glibc 2.36+ uses statx for directory traversal. + rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(statx)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add statx() syscall; " + "received libseccomp error %d", rc); + return rc; + } #endif } diff -Nru tor-0.4.8.16/src/lib/sandbox/sandbox.h tor-0.4.9.6/src/lib/sandbox/sandbox.h --- tor-0.4.8.16/src/lib/sandbox/sandbox.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/sandbox/sandbox.h 2026-03-25 14:30:34.000000000 +0000 @@ -16,6 +16,9 @@ #include "lib/cc/torint.h" #ifndef SYS_SECCOMP +#ifdef HAVE_SIGNAL_H +#include +#endif /** * Used by SIGSYS signal handler to check if the signal was issued due to a diff -Nru tor-0.4.8.16/src/lib/smartlist_core/include.am tor-0.4.9.6/src/lib/smartlist_core/include.am --- tor-0.4.8.16/src/lib/smartlist_core/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/smartlist_core/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -7,7 +7,7 @@ # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_smartlist_core_a_SOURCES = \ - src/lib/smartlist_core/smartlist_core.c \ + src/lib/smartlist_core/smartlist_core.c \ src/lib/smartlist_core/smartlist_split.c src_lib_libtor_smartlist_core_testing_a_SOURCES = \ @@ -18,6 +18,6 @@ # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ - src/lib/smartlist_core/smartlist_core.h \ - src/lib/smartlist_core/smartlist_foreach.h \ + src/lib/smartlist_core/smartlist_core.h \ + src/lib/smartlist_core/smartlist_foreach.h \ src/lib/smartlist_core/smartlist_split.h diff -Nru tor-0.4.8.16/src/lib/string/util_string.c tor-0.4.9.6/src/lib/string/util_string.c --- tor-0.4.8.16/src/lib/string/util_string.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/string/util_string.c 2026-03-25 14:30:34.000000000 +0000 @@ -31,6 +31,8 @@ { #if defined(HAVE_MEMMEM) && (!defined(__GNUC__) || __GNUC__ >= 2) raw_assert(nlen); + if (nlen > hlen) + return NULL; return memmem(_haystack, hlen, _needle, nlen); #else /* This isn't as fast as the GLIBC implementation, but it doesn't need to diff -Nru tor-0.4.8.16/src/lib/term/include.am tor-0.4.9.6/src/lib/term/include.am --- tor-0.4.8.16/src/lib/term/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/term/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -22,5 +22,5 @@ src_lib_libtor_term_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) # ADD_C_FILE: INSERT HEADERS HERE. -noinst_HEADERS += \ +noinst_HEADERS += \ src/lib/term/getpass.h diff -Nru tor-0.4.8.16/src/lib/time/compat_time.c tor-0.4.9.6/src/lib/time/compat_time.c --- tor-0.4.8.16/src/lib/time/compat_time.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/time/compat_time.c 2026-03-25 14:30:34.000000000 +0000 @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2021, The Tor Project, Inc. */ + * Copyright (c) 2007-2025, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -53,13 +53,15 @@ #undef HAVE_CLOCK_GETTIME #endif -#ifdef TOR_UNIT_TESTS -/** Delay for msec milliseconds. Only used in tests. */ +/** Delay for msec milliseconds. */ void tor_sleep_msec(int msec) { #ifdef _WIN32 Sleep(msec); +#elif defined(HAVE_TIME_H) + struct timespec ts = {msec / 1000, (msec % 1000) * 1000 * 1000}; + while (nanosleep(&ts, &ts) == -1 && errno == EINTR); #elif defined(HAVE_USLEEP) sleep(msec / 1000); /* Some usleep()s hate sleeping more than 1 sec */ @@ -71,7 +73,6 @@ sleep(CEIL_DIV(msec, 1000)); #endif /* defined(_WIN32) || ... */ } -#endif /* defined(TOR_UNIT_TESTS) */ #define ONE_MILLION ((int64_t) (1000 * 1000)) #define ONE_BILLION ((int64_t) (1000 * 1000 * 1000)) diff -Nru tor-0.4.8.16/src/lib/time/compat_time.h tor-0.4.9.6/src/lib/time/compat_time.h --- tor-0.4.8.16/src/lib/time/compat_time.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/time/compat_time.h 2026-03-25 14:30:34.000000000 +0000 @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2021, The Tor Project, Inc. */ + * Copyright (c) 2007-2025, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -361,9 +361,9 @@ #endif /* SIZEOF_VOID_P == 8 */ } -#ifdef TOR_UNIT_TESTS void tor_sleep_msec(int msec); +#ifdef TOR_UNIT_TESTS void monotime_enable_test_mocking(void); void monotime_disable_test_mocking(void); void monotime_set_mock_time_nsec(int64_t); diff -Nru tor-0.4.8.16/src/lib/time/include.am tor-0.4.9.6/src/lib/time/include.am --- tor-0.4.8.16/src/lib/time/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/time/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -6,7 +6,7 @@ endif # ADD_C_FILE: INSERT SOURCES HERE. -src_lib_libtor_time_a_SOURCES = \ +src_lib_libtor_time_a_SOURCES = \ src/lib/time/compat_time.c \ src/lib/time/time_sys.c \ src/lib/time/tvdiff.c diff -Nru tor-0.4.8.16/src/lib/tls/ciphers.inc tor-0.4.9.6/src/lib/tls/ciphers.inc --- tor-0.4.8.16/src/lib/tls/ciphers.inc 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/tls/ciphers.inc 2026-03-25 14:30:34.000000000 +0000 @@ -2,27 +2,8 @@ * advertise. Before including it, you should define the CIPHER and XCIPHER * macros. * - * This file was automatically generated by get_mozilla_ciphers.py; - * TLSv1.3 ciphers were added manually. + * This file was automatically generated by get_mozilla_ciphers.py. */ - -/* Here are the TLS1.3 ciphers. Note that we don't have XCIPHER instances - * here, since we don't want to ever fake them. - */ -#ifdef TLS1_3_TXT_AES_128_GCM_SHA256 - CIPHER(0x1301, TLS1_3_TXT_AES_128_GCM_SHA256) -#endif -#ifdef TLS1_3_TXT_AES_256_GCM_SHA384 - CIPHER(0x1302, TLS1_3_TXT_AES_256_GCM_SHA384) -#endif -#ifdef TLS1_3_TXT_CHACHA20_POLY1305_SHA256 - CIPHER(0x1303, TLS1_3_TXT_CHACHA20_POLY1305_SHA256) -#endif -#ifdef TLS1_3_TXT_AES_128_CCM_SHA256 - CIPHER(0x1304, TLS1_3_TXT_AES_128_CCM_SHA256) -#endif - -/* Here's the machine-generated list. */ #ifdef TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 CIPHER(0xc02b, TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) #else @@ -73,15 +54,15 @@ #else XCIPHER(0xc014, TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA) #endif -#ifdef TLS1_TXT_DHE_RSA_WITH_AES_128_SHA - CIPHER(0x0033, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA) +#ifdef TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256 + CIPHER(0x009c, TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256) #else - XCIPHER(0x0033, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA) + XCIPHER(0x009c, TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256) #endif -#ifdef TLS1_TXT_DHE_RSA_WITH_AES_256_SHA - CIPHER(0x0039, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) +#ifdef TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384 + CIPHER(0x009d, TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384) #else - XCIPHER(0x0039, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) + XCIPHER(0x009d, TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384) #endif #ifdef TLS1_TXT_RSA_WITH_AES_128_SHA CIPHER(0x002f, TLS1_TXT_RSA_WITH_AES_128_SHA) @@ -93,8 +74,3 @@ #else XCIPHER(0x0035, TLS1_TXT_RSA_WITH_AES_256_SHA) #endif -#ifdef SSL3_TXT_RSA_DES_192_CBC3_SHA - CIPHER(0x000a, SSL3_TXT_RSA_DES_192_CBC3_SHA) -#else - XCIPHER(0x000a, SSL3_TXT_RSA_DES_192_CBC3_SHA) -#endif diff -Nru tor-0.4.8.16/src/lib/tls/ciphers_v13.inc tor-0.4.9.6/src/lib/tls/ciphers_v13.inc --- tor-0.4.8.16/src/lib/tls/ciphers_v13.inc 1970-01-01 00:00:00.000000000 +0000 +++ tor-0.4.9.6/src/lib/tls/ciphers_v13.inc 2026-03-25 14:30:34.000000000 +0000 @@ -0,0 +1,15 @@ +/* Here are the TLS1.3 ciphers. Note that we don't have XCIPHER instances + * here, since we don't want to ever fake them. + * + * This matches Firefox's list: + * https://searchfox.org/mozilla-central/source/security/nss/lib/ssl/ssl3con.c#100 + */ +#ifdef TLS1_3_RFC_AES_128_GCM_SHA256 + CIPHER(0x1301, TLS1_3_RFC_AES_128_GCM_SHA256) +#endif +#ifdef TLS1_3_RFC_CHACHA20_POLY1305_SHA256 + CIPHER(0x1303, TLS1_3_RFC_CHACHA20_POLY1305_SHA256) +#endif +#ifdef TLS1_3_RFC_AES_256_GCM_SHA384 + CIPHER(0x1302, TLS1_3_RFC_AES_256_GCM_SHA384) +#endif diff -Nru tor-0.4.8.16/src/lib/tls/include.am tor-0.4.9.6/src/lib/tls/include.am --- tor-0.4.8.16/src/lib/tls/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/tls/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -33,6 +33,7 @@ # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ src/lib/tls/ciphers.inc \ + src/lib/tls/ciphers_v13.inc \ src/lib/tls/buffers_tls.h \ src/lib/tls/nss_countbytes.h \ src/lib/tls/tortls.h \ diff -Nru tor-0.4.8.16/src/lib/tls/tortls.c tor-0.4.9.6/src/lib/tls/tortls.c --- tor-0.4.8.16/src/lib/tls/tortls.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/tls/tortls.c 2026-03-25 14:30:34.000000000 +0000 @@ -93,19 +93,6 @@ return rv; } -/** - * Return the authentication key that we use to authenticate ourselves as a - * client in the V3 in-protocol handshake. - */ -crypto_pk_t * -tor_tls_get_my_client_auth_key(void) -{ - tor_tls_context_t *context = tor_tls_context_get(0); - if (! context) - return NULL; - return context->auth_key; -} - /** Increase the reference count of ctx. */ void tor_tls_context_incref(tor_tls_context_t *ctx) @@ -175,9 +162,8 @@ * If server_identity is NULL, this will not generate a server * TLS context. If TOR_TLS_CTX_IS_PUBLIC_SERVER is set in flags, use * the same TLS context for incoming and outgoing connections, and - * ignore client_identity. If one of TOR_TLS_CTX_USE_ECDHE_P{224,256} - * is set in flags, use that ECDHE group if possible; otherwise use - * the default ECDHE group. */ + * ignore client_identity. + */ int tor_tls_context_init(unsigned flags, crypto_pk_t *client_identity, @@ -407,47 +393,6 @@ tor_free(tls); } -/** If the provided tls connection is authenticated and has a - * certificate chain that is currently valid and signed, then set - * *identity_key to the identity certificate's key and return - * 0. Else, return -1 and log complaints with log-level severity. - */ -int -tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_t **identity) -{ - tor_x509_cert_impl_t *cert = NULL, *id_cert = NULL; - tor_x509_cert_t *peer_x509 = NULL, *id_x509 = NULL; - tor_assert(tls); - tor_assert(identity); - int rv = -1; - - try_to_extract_certs_from_tls(severity, tls, &cert, &id_cert); - if (!cert) - goto done; - if (!id_cert) { - log_fn(severity,LD_PROTOCOL,"No distinct identity certificate found"); - goto done; - } - peer_x509 = tor_x509_cert_new(cert); - id_x509 = tor_x509_cert_new(id_cert); - cert = id_cert = NULL; /* Prevent double-free */ - - if (! tor_tls_cert_is_valid(severity, peer_x509, id_x509, time(NULL), 0)) { - goto done; - } - - *identity = tor_tls_cert_get_key(id_x509); - rv = 0; - - done: - tor_x509_cert_impl_free(cert); - tor_x509_cert_impl_free(id_cert); - tor_x509_cert_free(peer_x509); - tor_x509_cert_free(id_x509); - - return rv; -} - static void subsys_tortls_shutdown(void) { diff -Nru tor-0.4.8.16/src/lib/tls/tortls.h tor-0.4.9.6/src/lib/tls/tortls.h --- tor-0.4.8.16/src/lib/tls/tortls.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/tls/tortls.h 2026-03-25 14:30:34.000000000 +0000 @@ -75,8 +75,6 @@ void tor_tls_free_all(void); #define TOR_TLS_CTX_IS_PUBLIC_SERVER (1u<<0) -#define TOR_TLS_CTX_USE_ECDHE_P256 (1u<<1) -#define TOR_TLS_CTX_USE_ECDHE_P224 (1u<<2) void tor_tls_init(void); void tls_log_errors(tor_tls_t *tls, int severity, int domain, @@ -91,9 +89,6 @@ tor_tls_context_t *tor_tls_context_get(int is_server); tor_tls_t *tor_tls_new(tor_socket_t sock, int is_server); void tor_tls_set_logged_address(tor_tls_t *tls, const char *address); -void tor_tls_set_renegotiate_callback(tor_tls_t *tls, - void (*cb)(tor_tls_t *, void *arg), - void *arg); int tor_tls_is_server(tor_tls_t *tls); void tor_tls_release_socket(tor_tls_t *tls); void tor_tls_free_(tor_tls_t *tls); @@ -101,13 +96,9 @@ int tor_tls_peer_has_cert(tor_tls_t *tls); MOCK_DECL(struct tor_x509_cert_t *,tor_tls_get_peer_cert,(tor_tls_t *tls)); MOCK_DECL(struct tor_x509_cert_t *,tor_tls_get_own_cert,(tor_tls_t *tls)); -int tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_t **identity); MOCK_DECL(int, tor_tls_read, (tor_tls_t *tls, char *cp, size_t len)); int tor_tls_write(tor_tls_t *tls, const char *cp, size_t n); int tor_tls_handshake(tor_tls_t *tls); -int tor_tls_finish_handshake(tor_tls_t *tls); -void tor_tls_unblock_renegotiation(tor_tls_t *tls); -void tor_tls_block_renegotiation(tor_tls_t *tls); int tor_tls_get_pending_bytes(tor_tls_t *tls); size_t tor_tls_get_forced_write_size(tor_tls_t *tls); @@ -120,16 +111,8 @@ MOCK_DECL(double, tls_get_write_overhead_ratio, (void)); -int tor_tls_used_v1_handshake(tor_tls_t *tls); -int tor_tls_get_num_server_handshakes(tor_tls_t *tls); -int tor_tls_server_got_renegotiate(tor_tls_t *tls); MOCK_DECL(int,tor_tls_cert_matches_key,(const tor_tls_t *tls, const struct tor_x509_cert_t *cert)); -MOCK_DECL(int,tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out)); -#ifdef ENABLE_OPENSSL -/* OpenSSL lets us see these master secrets; NSS sensibly does not. */ -#define HAVE_WORKING_TOR_TLS_GET_TLSSECRETS -#endif MOCK_DECL(int,tor_tls_export_key_material,( tor_tls_t *tls, uint8_t *secrets_out, const uint8_t *context, @@ -151,9 +134,6 @@ int tor_tls_get_my_certs(int server, const struct tor_x509_cert_t **link_cert_out, const struct tor_x509_cert_t **id_cert_out); -crypto_pk_t *tor_tls_get_my_client_auth_key(void); - -const char *tor_tls_get_ciphersuite_name(tor_tls_t *tls); int evaluate_ecgroup_for_tls(const char *ecgroup); diff -Nru tor-0.4.8.16/src/lib/tls/tortls_internal.h tor-0.4.9.6/src/lib/tls/tortls_internal.h --- tor-0.4.8.16/src/lib/tls/tortls_internal.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/tls/tortls_internal.h 2026-03-25 14:30:34.000000000 +0000 @@ -18,10 +18,6 @@ int tor_tls_get_error(tor_tls_t *tls, int r, int extra, const char *doing, int severity, int domain); #endif -MOCK_DECL(void, try_to_extract_certs_from_tls, - (int severity, tor_tls_t *tls, - tor_x509_cert_impl_t **cert_out, - tor_x509_cert_impl_t **id_cert_out)); tor_tls_context_t *tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime, unsigned flags, int is_client); @@ -44,30 +40,14 @@ #ifdef ENABLE_OPENSSL tor_tls_t *tor_tls_get_by_ssl(const struct ssl_st *ssl); -int tor_tls_client_is_using_v2_ciphers(const struct ssl_st *ssl); void tor_tls_debug_state_callback(const struct ssl_st *ssl, int type, int val); void tor_tls_server_info_callback(const struct ssl_st *ssl, int type, int val); void tor_tls_allocate_tor_tls_object_ex_data_index(void); -#if !defined(HAVE_SSL_SESSION_GET_MASTER_KEY) -size_t SSL_SESSION_get_master_key(struct ssl_session_st *s, - uint8_t *out, - size_t len); -#endif - #ifdef TORTLS_OPENSSL_PRIVATE int always_accept_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx); -int tor_tls_classify_client_ciphers(const struct ssl_st *ssl, - STACK_OF(SSL_CIPHER) *peer_ciphers); -STATIC int tor_tls_session_secret_cb(struct ssl_st *ssl, void *secret, - int *secret_len, - STACK_OF(SSL_CIPHER) *peer_ciphers, - CONST_IF_OPENSSL_1_1_API SSL_CIPHER **cipher, - void *arg); -STATIC int find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m, - uint16_t cipher); #endif /* defined(TORTLS_OPENSSL_PRIVATE) */ #endif /* defined(ENABLE_OPENSSL) */ diff -Nru tor-0.4.8.16/src/lib/tls/tortls_nss.c tor-0.4.9.6/src/lib/tls/tortls_nss.c --- tor-0.4.8.16/src/lib/tls/tortls_nss.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/tls/tortls_nss.c 2026-03-25 14:30:34.000000000 +0000 @@ -46,34 +46,6 @@ static SECStatus always_accept_cert_cb(void *, PRFileDesc *, PRBool, PRBool); -MOCK_IMPL(void, -try_to_extract_certs_from_tls,(int severity, tor_tls_t *tls, - tor_x509_cert_impl_t **cert_out, - tor_x509_cert_impl_t **id_cert_out)) -{ - tor_assert(tls); - tor_assert(cert_out); - tor_assert(id_cert_out); - (void) severity; - - *cert_out = *id_cert_out = NULL; - - CERTCertificate *peer = SSL_PeerCertificate(tls->ssl); - if (!peer) - return; - *cert_out = peer; /* Now owns pointer. */ - - CERTCertList *chain = SSL_PeerCertificateChain(tls->ssl); - CERTCertListNode *c = CERT_LIST_HEAD(chain); - for (; !CERT_LIST_END(c, chain); c = CERT_LIST_NEXT(c)) { - if (CERT_CompareCerts(c->cert, peer) == PR_FALSE) { - *id_cert_out = CERT_DupCertificate(c->cert); - break; - } - } - CERT_DestroyCertList(chain); -} - static bool we_like_ssl_cipher(SSLCipherAlgorithm ca) { @@ -104,6 +76,11 @@ case ssl_kea_ecdh_psk: return false; case ssl_kea_dh_psk: return false; +#ifdef NSS_HAS_ECDH_HYBRID + case ssl_kea_ecdh_hybrid_psk: return false; + case ssl_kea_ecdh_hybrid: return true; +#endif + case ssl_kea_dh: return true; case ssl_kea_ecdh: return true; case ssl_kea_tls13_any: return true; @@ -464,18 +441,6 @@ return tls; } -void -tor_tls_set_renegotiate_callback(tor_tls_t *tls, - void (*cb)(tor_tls_t *, void *arg), - void *arg) -{ - tor_assert(tls); - (void)cb; - (void)arg; - - /* We don't support renegotiation-based TLS with NSS. */ -} - /** * Tell the TLS library that the underlying socket for tls has been * closed, and the library should not attempt to free that socket itself. @@ -619,7 +584,7 @@ if (s == SECSuccess) { tls->state = TOR_TLS_ST_OPEN; log_debug(LD_NET, "SSL handshake is supposedly complete."); - return tor_tls_finish_handshake(tls); + return TOR_TLS_DONE; } if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) return TOR_TLS_WANTREAD; /* XXXX What about wantwrite? */ @@ -628,29 +593,6 @@ } int -tor_tls_finish_handshake(tor_tls_t *tls) -{ - tor_assert(tls); - // We don't need to do any of the weird handshake nonsense stuff on NSS, - // since we only support recent handshakes. - return TOR_TLS_DONE; -} - -void -tor_tls_unblock_renegotiation(tor_tls_t *tls) -{ - tor_assert(tls); - /* We don't support renegotiation with NSS. */ -} - -void -tor_tls_block_renegotiation(tor_tls_t *tls) -{ - tor_assert(tls); - /* We don't support renegotiation with NSS. */ -} - -int tor_tls_get_pending_bytes(tor_tls_t *tls) { tor_assert(tls); @@ -713,22 +655,6 @@ return 0.95; } -int -tor_tls_used_v1_handshake(tor_tls_t *tls) -{ - tor_assert(tls); - /* We don't support or allow the V1 handshake with NSS. - */ - return 0; -} - -int -tor_tls_server_got_renegotiate(tor_tls_t *tls) -{ - tor_assert(tls); - return 0; /* We don't support renegotiation with NSS */ -} - MOCK_IMPL(int, tor_tls_cert_matches_key,(const tor_tls_t *tls, const struct tor_x509_cert_t *cert)) @@ -789,17 +715,6 @@ } MOCK_IMPL(int, -tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out)) -{ - tor_assert(tls); - tor_assert(secrets_out); - - /* There's no way to get this information out of NSS. */ - - return -1; -} - -MOCK_IMPL(int, tor_tls_export_key_material,(tor_tls_t *tls, uint8_t *secrets_out, const uint8_t *context, size_t context_len, @@ -829,30 +744,6 @@ return (s == SECSuccess) ? 0 : -1; } -const char * -tor_tls_get_ciphersuite_name(tor_tls_t *tls) -{ - tor_assert(tls); - - SSLChannelInfo channel_info; - SSLCipherSuiteInfo cipher_info; - - memset(&channel_info, 0, sizeof(channel_info)); - memset(&cipher_info, 0, sizeof(cipher_info)); - - SECStatus s = SSL_GetChannelInfo(tls->ssl, - &channel_info, sizeof(channel_info)); - if (s != SECSuccess) - return NULL; - - s = SSL_GetCipherSuiteInfo(channel_info.cipherSuite, - &cipher_info, sizeof(cipher_info)); - if (s != SECSuccess) - return NULL; - - return cipher_info.cipherSuiteName; -} - /** The group we should use for ecdhe when none was selected. */ #define SEC_OID_TOR_DEFAULT_ECDHE_GROUP SEC_OID_ANSIX962_EC_PRIME256V1 diff -Nru tor-0.4.8.16/src/lib/tls/tortls_openssl.c tor-0.4.9.6/src/lib/tls/tortls_openssl.c --- tor-0.4.8.16/src/lib/tls/tortls_openssl.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/tls/tortls_openssl.c 2026-03-25 14:30:34.000000000 +0000 @@ -80,46 +80,9 @@ #define ADDR(tls) (((tls) && (tls)->address) ? tls->address : "peer") -#if OPENSSL_VERSION_NUMBER < OPENSSL_V(1,0,0,'f') -/* This is a version of OpenSSL before 1.0.0f. It does not have - * the CVE-2011-4576 fix, and as such it can't use RELEASE_BUFFERS and - * SSL3 safely at the same time. - */ -#define DISABLE_SSL3_HANDSHAKE -#endif /* OPENSSL_VERSION_NUMBER < OPENSSL_V(1,0,0,'f') */ - -/* We redefine these so that we can run correctly even if the vendor gives us - * a version of OpenSSL that does not match its header files. (Apple: I am - * looking at you.) - */ -#ifndef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION -#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000L -#endif -#ifndef SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION -#define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x0010 -#endif - /** Set to true iff openssl bug 7712 has been detected. */ static int openssl_bug_7712_is_present = 0; -/** Return values for tor_tls_classify_client_ciphers. - * - * @{ - */ -/** An error occurred when examining the client ciphers */ -#define CIPHERS_ERR -1 -/** The client cipher list indicates that a v1 handshake was in use. */ -#define CIPHERS_V1 1 -/** The client cipher list indicates that the client is using the v2 or the - * v3 handshake, but that it is (probably!) lying about what ciphers it - * supports */ -#define CIPHERS_V2 2 -/** The client cipher list indicates that the client is using the v2 or the - * v3 handshake, and that it is telling the truth about what ciphers it - * supports */ -#define CIPHERS_UNRESTRICTED 3 -/** @} */ - /** The ex_data index in which we store a pointer to an SSL object's * corresponding tor_tls_t object. */ STATIC int tor_tls_object_ex_data_index = -1; @@ -208,9 +171,6 @@ case SSL_R_HTTP_REQUEST: case SSL_R_HTTPS_PROXY_REQUEST: case SSL_R_RECORD_LENGTH_MISMATCH: -#ifndef OPENSSL_1_1_API - case SSL_R_RECORD_TOO_LARGE: -#endif case SSL_R_UNKNOWN_PROTOCOL: case SSL_R_UNSUPPORTED_PROTOCOL: severity = LOG_INFO; @@ -333,48 +293,7 @@ check_no_tls_errors(); if (!tls_library_is_initialized) { -#ifdef OPENSSL_1_1_API OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); -#else - SSL_library_init(); - SSL_load_error_strings(); -#endif /* defined(OPENSSL_1_1_API) */ - -#if (SIZEOF_VOID_P >= 8 && \ - OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,1) && \ - (!defined(LIBRESSL_VERSION_NUMBER) || \ - LIBRESSL_VERSION_NUMBER < 0x3080000fL)) - long version = tor_OpenSSL_version_num(); - - /* LCOV_EXCL_START : we can't test these lines on the same machine */ - if (version >= OPENSSL_V_SERIES(1,0,1)) { - /* Warn if we could *almost* be running with much faster ECDH. - If we're built for a 64-bit target, using OpenSSL 1.0.1, but we - don't have one of the built-in __uint128-based speedups, we are - just one build operation away from an accelerated handshake. - - (We could be looking at OPENSSL_NO_EC_NISTP_64_GCC_128 instead of - doing this test, but that gives compile-time options, not runtime - behavior.) - */ - EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - const EC_GROUP *g = key ? EC_KEY_get0_group(key) : NULL; - const EC_METHOD *m = g ? EC_GROUP_method_of(g) : NULL; - const int warn = (m == EC_GFp_simple_method() || - m == EC_GFp_mont_method() || - m == EC_GFp_nist_method()); - EC_KEY_free(key); - - if (warn) - log_notice(LD_GENERAL, "We were built to run on a 64-bit CPU, with " - "OpenSSL 1.0.1 or later, but with a version of OpenSSL " - "that apparently lacks accelerated support for the NIST " - "P-224 and P-256 groups. Building openssl with such " - "support (using the enable-ec_nistp_64_gcc_128 option " - "when configuring it) would make ECDH much faster."); - } - /* LCOV_EXCL_STOP */ -#endif /* (SIZEOF_VOID_P >= 8 && ... */ tor_tls_allocate_tor_tls_object_ex_data_index(); @@ -395,37 +314,8 @@ return 1; } -/** List of ciphers that servers should select from when the client might be - * claiming extra unsupported ciphers in order to avoid fingerprinting. */ -static const char SERVER_CIPHER_LIST[] = -#ifdef TLS1_3_TXT_AES_128_GCM_SHA256 - /* This one can never actually get selected, since if the client lists it, - * we will assume that the client is honest, and not use this list. - * Nonetheless we list it if it's available, so that the server doesn't - * conclude that it has no valid ciphers if it's running with TLS1.3. - */ - TLS1_3_TXT_AES_128_GCM_SHA256 ":" -#endif /* defined(TLS1_3_TXT_AES_128_GCM_SHA256) */ - TLS1_TXT_DHE_RSA_WITH_AES_256_SHA ":" - TLS1_TXT_DHE_RSA_WITH_AES_128_SHA; - -/** List of ciphers that servers should select from when we actually have - * our choice of what cipher to use. */ -static const char UNRESTRICTED_SERVER_CIPHER_LIST[] = - /* Here are the TLS 1.3 ciphers we like, in the order we prefer. */ -#ifdef TLS1_3_TXT_AES_256_GCM_SHA384 - TLS1_3_TXT_AES_256_GCM_SHA384 ":" -#endif -#ifdef TLS1_3_TXT_CHACHA20_POLY1305_SHA256 - TLS1_3_TXT_CHACHA20_POLY1305_SHA256 ":" -#endif -#ifdef TLS1_3_TXT_AES_128_GCM_SHA256 - TLS1_3_TXT_AES_128_GCM_SHA256 ":" -#endif -#ifdef TLS1_3_TXT_AES_128_CCM_SHA256 - TLS1_3_TXT_AES_128_CCM_SHA256 ":" -#endif - +/** List of ciphers that servers should select from when using TLS 1.2 */ +static const char UNRESTRICTED_TLS1_2_SERVER_CIPHER_LIST[] = /* This list is autogenerated with the gen_server_ciphers.py script; * don't hand-edit it. */ #ifdef TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 @@ -493,6 +383,12 @@ * of any cipher we say. */ "!SSLv2" ; +static char CLIENT_CIPHER_LIST_TLSv13[] = +#ifndef COCCI +#include "lib/tls/ciphers_v13.inc" +#endif + "" + ; #undef CIPHER #undef XCIPHER @@ -558,32 +454,17 @@ } } -#if 0 - /* Tell OpenSSL to only use TLS1. This may have subtly different results - * from SSLv23_method() with SSLv2 and SSLv3 disabled, so we need to do some - * investigation before we consider adjusting it. It should be compatible - * with existing Tors. */ - if (!(result->ctx = SSL_CTX_new(TLSv1_method()))) - goto error; -#endif /* 0 */ - - /* Tell OpenSSL to use TLS 1.0 or later but not SSL2 or SSL3. */ -#ifdef HAVE_TLS_METHOD + /* Tell OpenSSL to use TLS 1.2 or later. */ if (!(result->ctx = SSL_CTX_new(TLS_method()))) goto error; -#else - if (!(result->ctx = SSL_CTX_new(SSLv23_method()))) + if (!SSL_CTX_set_min_proto_version(result->ctx, TLS1_2_VERSION)) goto error; -#endif /* defined(HAVE_TLS_METHOD) */ #ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL /* Level 1 re-enables RSA1024 and DH1024 for compatibility with old tors */ SSL_CTX_set_security_level(result->ctx, 1); #endif - SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv2); - SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv3); - /* Prefer the server's ordering of ciphers: the client's ordering has * historically been chosen for fingerprinting resistance. */ SSL_CTX_set_options(result->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); @@ -611,13 +492,12 @@ SSL_CTX_set_options(result->ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif - /* Yes, we know what we are doing here. No, we do not treat a renegotiation - * as authenticating any earlier-received data. - */ - { - SSL_CTX_set_options(result->ctx, - SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); - } +#ifdef SSL_OP_NO_RENEGOTIATION + SSL_CTX_set_options(result->ctx, SSL_OP_NO_RENEGOTIATION); +#endif +#ifdef SSL_OP_NO_CLIENT_RENEGOTIATION + SSL_CTX_set_options(result->ctx, SSL_OP_NO_CLIENT_RENEGOTIATION); +#endif /* Don't actually allow compression; it uses RAM and time, it makes TLS * vulnerable to CRIME-style attacks, and most of the data we transmit over @@ -625,12 +505,6 @@ #ifdef SSL_OP_NO_COMPRESSION SSL_CTX_set_options(result->ctx, SSL_OP_NO_COMPRESSION); #endif -#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0) -#ifndef OPENSSL_NO_COMP - if (result->ctx->comp_methods) - result->ctx->comp_methods = NULL; -#endif -#endif /* OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,1,0) */ #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(result->ctx, SSL_MODE_RELEASE_BUFFERS); @@ -641,11 +515,10 @@ result->my_link_cert->cert)) { goto error; } - if (result->my_id_cert) { - X509_STORE *s = SSL_CTX_get_cert_store(result->ctx); - tor_assert(s); - X509_STORE_add_cert(s, result->my_id_cert->cert); - } + // Here we would once add my_id_cert too via X509_STORE_add_cert. + // + // We no longer do that, since we no longer send multiple certs; + // that was part of the obsolete v1 handshake. } SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF); if (!is_client) { @@ -666,40 +539,78 @@ SSL_CTX_set_tmp_dh(result->ctx, dh); DH_free(dh); } -/* We check for this function in two ways, since it might be either a symbol - * or a macro. */ -#if defined(SSL_CTX_set1_groups_list) || defined(HAVE_SSL_CTX_SET1_GROUPS_LIST) + { - const char *list; - if (flags & TOR_TLS_CTX_USE_ECDHE_P224) - list = "P-224:P-256"; - else if (flags & TOR_TLS_CTX_USE_ECDHE_P256) - list = "P-256:P-224"; - else - list = "P-256:P-224"; - int r = (int) SSL_CTX_set1_groups_list(result->ctx, list); - if (r < 0) - goto error; + // We'd like to say something like: + // "?X25519MLKEM768:P-256:P-224" + // to mean that we prefer X25519MLKEM768 if it is present; + // but we do insist on the presence of P-256 and P-224. + // + // Unfortunately, we support back to OpenSSL 3.0, which did not provide + // any syntax for saying "don't worry if this group isn't supported." + // Instead, we have to make this preference list of preference lists. + static const struct { + // Minimal version with which to try this syntax. + // We have to restrict, since older versions of openssl + // can misunderstand-but nonetheless accept!-syntaxes + // supported by newer versions. See #41058 for one example. + long min_version; + const char *groups; + } group_lists[] = { + // We do use the ? syntax here, since every version of OpenSSL + // that supports ML-KEM also supports the ? syntax. + // We also use the * and / syntaxes: + // '*' indicates that the client should send these keyshares. + // "/" separates tuples of groups that are "comparably secure". + // + // Note that we tell the client to send a P-256 keyshare, since until + // this commit, our servers didn't accept X25519. + // + // Also note that until the upstream LibreSSL bug from tor#41134 gets + // fixed, the order of groups common between each preference list must + // be the same. We can't prefer P-256 in one, and X25519 in another. + { + OPENSSL_V_SERIES(3,5,0), + "?*X25519MLKEM768 / ?SecP256r1MLKEM768 / *P-256:?X25519:P-224" + }, + { 0, "P-256:X25519:P-224" }, + { 0, "P-256:P-224" }, + }; + bool success = false; + long our_version = tor_OpenSSL_version_num(); + for (unsigned j = 0; j < ARRAY_LENGTH(group_lists); ++j) { + const char *list = group_lists[j].groups; + if (group_lists[j].min_version > our_version) { + log_info(LD_NET, "Not trying groups %s because of OpenSSL version.", + list); + continue; + } + int r = (int) SSL_CTX_set1_groups_list(result->ctx, list); + if (r == 1) { + static bool have_logged_already = false; + if (!have_logged_already) { + /* say it only once at startup, since the answer won't change */ + log_notice(LD_NET, "Set list of supported TLS groups to: %s", list); + have_logged_already = true; + } + success = true; + break; + } + log_info(LD_NET, "Group list %s wasn't accepted", list); + } + if (! success) { + log_warn(LD_NET, "No lists of TLS groups were supported. " + "Using library defaults"); + } + } + + if (is_client) { + SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER, + always_accept_verify_cb); + } else { + /* Don't send a certificate request at all if we're not a client. */ + SSL_CTX_set_verify(result->ctx, SSL_VERIFY_NONE, NULL); } -#else /* !(defined(SSL_CTX_set1_groups_list) || defined(HAVE_SSL_CTX_SE...)) */ - if (! is_client) { - int nid; - EC_KEY *ec_key; - if (flags & TOR_TLS_CTX_USE_ECDHE_P224) - nid = NID_secp224r1; - else if (flags & TOR_TLS_CTX_USE_ECDHE_P256) - nid = NID_X9_62_prime256v1; - else - nid = NID_tor_default_ecdhe_group; - /* Use P-256 for ECDHE. */ - ec_key = EC_KEY_new_by_curve_name(nid); - if (ec_key != NULL) /*XXXX Handle errors? */ - SSL_CTX_set_tmp_ecdh(result->ctx, ec_key); - EC_KEY_free(ec_key); - } -#endif /* defined(SSL_CTX_set1_groups_list) || defined(HAVE_SSL_CTX_SET1...) */ - SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER, - always_accept_verify_cb); /* let us realloc bufs that we're writing from */ SSL_CTX_set_mode(result->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); @@ -729,336 +640,6 @@ /* LCOV_EXCL_STOP */ } -/* Return the name of the negotiated ciphersuite in use on tls */ -const char * -tor_tls_get_ciphersuite_name(tor_tls_t *tls) -{ - return SSL_get_cipher(tls->ssl); -} - -/* Here's the old V2 cipher list we sent from 0.2.1.1-alpha up to - * 0.2.3.17-beta. If a client is using this list, we can't believe the ciphers - * that it claims to support. We'll prune this list to remove the ciphers - * *we* don't recognize. */ -STATIC uint16_t v2_cipher_list[] = { - 0xc00a, /* TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA */ - 0xc014, /* TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA */ - 0x0039, /* TLS1_TXT_DHE_RSA_WITH_AES_256_SHA */ - 0x0038, /* TLS1_TXT_DHE_DSS_WITH_AES_256_SHA */ - 0xc00f, /* TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA */ - 0xc005, /* TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA */ - 0x0035, /* TLS1_TXT_RSA_WITH_AES_256_SHA */ - 0xc007, /* TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA */ - 0xc009, /* TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA */ - 0xc011, /* TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA */ - 0xc013, /* TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA */ - 0x0033, /* TLS1_TXT_DHE_RSA_WITH_AES_128_SHA */ - 0x0032, /* TLS1_TXT_DHE_DSS_WITH_AES_128_SHA */ - 0xc00c, /* TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA */ - 0xc00e, /* TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA */ - 0xc002, /* TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA */ - 0xc004, /* TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA */ - 0x0004, /* SSL3_TXT_RSA_RC4_128_MD5 */ - 0x0005, /* SSL3_TXT_RSA_RC4_128_SHA */ - 0x002f, /* TLS1_TXT_RSA_WITH_AES_128_SHA */ - 0xc008, /* TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA */ - 0xc012, /* TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA */ - 0x0016, /* SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA */ - 0x0013, /* SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA */ - 0xc00d, /* TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA */ - 0xc003, /* TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA */ - 0xfeff, /* SSL3_TXT_RSA_FIPS_WITH_3DES_EDE_CBC_SHA */ - 0x000a, /* SSL3_TXT_RSA_DES_192_CBC3_SHA */ - 0 -}; -/** Have we removed the unrecognized ciphers from v2_cipher_list yet? */ -static int v2_cipher_list_pruned = 0; - -/** Return 0 if m does not support the cipher with ID cipher; - * return 1 if it does support it, or if we have no way to tell. */ -int -find_cipher_by_id(const SSL *ssl, const SSL_METHOD *m, uint16_t cipher) -{ - const SSL_CIPHER *c; -#ifdef HAVE_SSL_CIPHER_FIND - (void) m; - { - unsigned char cipherid[3]; - tor_assert(ssl); - set_uint16(cipherid, tor_htons(cipher)); - cipherid[2] = 0; /* If ssl23_get_cipher_by_char finds no cipher starting - * with a two-byte 'cipherid', it may look for a v2 - * cipher with the appropriate 3 bytes. */ - c = SSL_CIPHER_find((SSL*)ssl, cipherid); - if (c) - tor_assert((SSL_CIPHER_get_id(c) & 0xffff) == cipher); - return c != NULL; - } -#else /* !defined(HAVE_SSL_CIPHER_FIND) */ - -# if defined(HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR) - if (m && m->get_cipher_by_char) { - unsigned char cipherid[3]; - set_uint16(cipherid, tor_htons(cipher)); - cipherid[2] = 0; /* If ssl23_get_cipher_by_char finds no cipher starting - * with a two-byte 'cipherid', it may look for a v2 - * cipher with the appropriate 3 bytes. */ - c = m->get_cipher_by_char(cipherid); - if (c) - tor_assert((c->id & 0xffff) == cipher); - return c != NULL; - } -#endif /* defined(HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR) */ -# ifndef OPENSSL_1_1_API - if (m && m->get_cipher && m->num_ciphers) { - /* It would seem that some of the "let's-clean-up-openssl" forks have - * removed the get_cipher_by_char function. Okay, so now you get a - * quadratic search. - */ - int i; - for (i = 0; i < m->num_ciphers(); ++i) { - c = m->get_cipher(i); - if (c && (c->id & 0xffff) == cipher) { - return 1; - } - } - return 0; - } -#endif /* !defined(OPENSSL_1_1_API) */ - (void) ssl; - (void) m; - (void) cipher; - return 1; /* No way to search */ -#endif /* defined(HAVE_SSL_CIPHER_FIND) */ -} - -/** Remove from v2_cipher_list every cipher that we don't support, so that - * comparing v2_cipher_list to a client's cipher list will give a sensible - * result. */ -static void -prune_v2_cipher_list(const SSL *ssl) -{ - uint16_t *inp, *outp; -#ifdef HAVE_TLS_METHOD - const SSL_METHOD *m = TLS_method(); -#else - const SSL_METHOD *m = SSLv23_method(); -#endif - - inp = outp = v2_cipher_list; - while (*inp) { - if (find_cipher_by_id(ssl, m, *inp)) { - *outp++ = *inp++; - } else { - inp++; - } - } - *outp = 0; - - v2_cipher_list_pruned = 1; -} - -/** Examine the client cipher list in ssl, and determine what kind of - * client it is. Return one of CIPHERS_ERR, CIPHERS_V1, CIPHERS_V2, - * CIPHERS_UNRESTRICTED. - **/ -int -tor_tls_classify_client_ciphers(const SSL *ssl, - STACK_OF(SSL_CIPHER) *peer_ciphers) -{ - int i, res; - tor_tls_t *tor_tls; - if (PREDICT_UNLIKELY(!v2_cipher_list_pruned)) - prune_v2_cipher_list(ssl); - - tor_tls = tor_tls_get_by_ssl(ssl); - if (tor_tls && tor_tls->client_cipher_list_type) - return tor_tls->client_cipher_list_type; - - /* If we reached this point, we just got a client hello. See if there is - * a cipher list. */ - if (!peer_ciphers) { - log_info(LD_NET, "No ciphers on session"); - res = CIPHERS_ERR; - goto done; - } - /* Now we need to see if there are any ciphers whose presence means we're - * dealing with an updated Tor. */ - for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) { - const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i); - const char *ciphername = SSL_CIPHER_get_name(cipher); - if (strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_128_SHA) && - strcmp(ciphername, TLS1_TXT_DHE_RSA_WITH_AES_256_SHA) && - strcmp(ciphername, SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) && - strcmp(ciphername, "(NONE)")) { - log_debug(LD_NET, "Got a non-version-1 cipher called '%s'", ciphername); - // return 1; - goto v2_or_higher; - } - } - res = CIPHERS_V1; - goto done; - v2_or_higher: - { - const uint16_t *v2_cipher = v2_cipher_list; - for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) { - const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i); - uint16_t id = SSL_CIPHER_get_id(cipher) & 0xffff; - if (id == 0x00ff) /* extended renegotiation indicator. */ - continue; - if (!id || id != *v2_cipher) { - res = CIPHERS_UNRESTRICTED; - goto dump_ciphers; - } - ++v2_cipher; - } - if (*v2_cipher != 0) { - res = CIPHERS_UNRESTRICTED; - goto dump_ciphers; - } - res = CIPHERS_V2; - } - - dump_ciphers: - { - smartlist_t *elts = smartlist_new(); - char *s; - for (i = 0; i < sk_SSL_CIPHER_num(peer_ciphers); ++i) { - const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(peer_ciphers, i); - const char *ciphername = SSL_CIPHER_get_name(cipher); - smartlist_add(elts, (char*)ciphername); - } - s = smartlist_join_strings(elts, ":", 0, NULL); - log_debug(LD_NET, "Got a %s V2/V3 cipher list from %s. It is: '%s'", - (res == CIPHERS_V2) ? "fictitious" : "real", ADDR(tor_tls), s); - tor_free(s); - smartlist_free(elts); - } - done: - if (tor_tls && peer_ciphers) - return tor_tls->client_cipher_list_type = res; - - return res; -} - -/** Return true iff the cipher list suggested by the client for ssl is - * a list that indicates that the client knows how to do the v2 TLS connection - * handshake. */ -int -tor_tls_client_is_using_v2_ciphers(const SSL *ssl) -{ - STACK_OF(SSL_CIPHER) *ciphers; -#ifdef HAVE_SSL_GET_CLIENT_CIPHERS - ciphers = SSL_get_client_ciphers(ssl); -#else - SSL_SESSION *session; - if (!(session = SSL_get_session((SSL *)ssl))) { - log_info(LD_NET, "No session on TLS?"); - return CIPHERS_ERR; - } - ciphers = session->ciphers; -#endif /* defined(HAVE_SSL_GET_CLIENT_CIPHERS) */ - - return tor_tls_classify_client_ciphers(ssl, ciphers) >= CIPHERS_V2; -} - -/** Invoked when we're accepting a connection on ssl, and the connection - * changes state. We use this: - *

  • To alter the state of the handshake partway through, so we - * do not send or request extra certificates in v2 handshakes.
  • - *
  • To detect renegotiation
- */ -void -tor_tls_server_info_callback(const SSL *ssl, int type, int val) -{ - tor_tls_t *tls; - (void) val; - - IF_BUG_ONCE(ssl == NULL) { - return; // LCOV_EXCL_LINE - } - - tor_tls_debug_state_callback(ssl, type, val); - - if (type != SSL_CB_ACCEPT_LOOP) - return; - - OSSL_HANDSHAKE_STATE ssl_state = SSL_get_state(ssl); - if (! STATE_IS_SW_SERVER_HELLO(ssl_state)) - return; - tls = tor_tls_get_by_ssl(ssl); - if (tls) { - /* Check whether we're watching for renegotiates. If so, this is one! */ - if (tls->negotiated_callback) - tls->got_renegotiate = 1; - } else { - log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!"); - return; - } - - /* Now check the cipher list. */ - if (tor_tls_client_is_using_v2_ciphers(ssl)) { - if (tls->wasV2Handshake) - return; /* We already turned this stuff off for the first handshake; - * This is a renegotiation. */ - - /* Yes, we're casting away the const from ssl. This is very naughty of us. - * Let's hope openssl doesn't notice! */ - - /* Set SSL_MODE_NO_AUTO_CHAIN to keep from sending back any extra certs. */ - SSL_set_mode((SSL*) ssl, SSL_MODE_NO_AUTO_CHAIN); - /* Don't send a hello request. */ - SSL_set_verify((SSL*) ssl, SSL_VERIFY_NONE, NULL); - - if (tls) { - tls->wasV2Handshake = 1; - } else { - /* LCOV_EXCL_START this line is not reachable */ - log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!"); - /* LCOV_EXCL_STOP */ - } - } -} - -/** Callback to get invoked on a server after we've read the list of ciphers - * the client supports, but before we pick our own ciphersuite. - * - * We can't abuse an info_cb for this, since by the time one of the - * client_hello info_cbs is called, we've already picked which ciphersuite to - * use. - * - * Technically, this function is an abuse of this callback, since the point of - * a session_secret_cb is to try to set up and/or verify a shared-secret for - * authentication on the fly. But as long as we return 0, we won't actually be - * setting up a shared secret, and all will be fine. - */ -int -tor_tls_session_secret_cb(SSL *ssl, void *secret, int *secret_len, - STACK_OF(SSL_CIPHER) *peer_ciphers, - CONST_IF_OPENSSL_1_1_API SSL_CIPHER **cipher, - void *arg) -{ - (void) secret; - (void) secret_len; - (void) peer_ciphers; - (void) cipher; - (void) arg; - - if (tor_tls_classify_client_ciphers(ssl, peer_ciphers) == - CIPHERS_UNRESTRICTED) { - SSL_set_cipher_list(ssl, UNRESTRICTED_SERVER_CIPHER_LIST); - } - - SSL_set_session_secret_cb(ssl, NULL, NULL); - - return 0; -} -static void -tor_tls_setup_session_secret_cb(tor_tls_t *tls) -{ - SSL_set_session_secret_cb(tls->ssl, tor_tls_session_secret_cb, NULL); -} - /** Create a new TLS object from a file descriptor, and a flag to * determine whether it is functioning as a server. */ @@ -1094,8 +675,26 @@ } #endif /* defined(SSL_CTRL_SET_MAX_PROTO_VERSION) */ - if (!SSL_set_cipher_list(result->ssl, - isServer ? SERVER_CIPHER_LIST : CLIENT_CIPHER_LIST)) { + /* Contrary to SSL_set_cipher_list(), TLSv1.3 SSL_set_ciphersuites() does NOT + * accept the final ':' so we have to strip it out. */ + size_t TLSv13len = strlen(CLIENT_CIPHER_LIST_TLSv13); + if (TLSv13len && CLIENT_CIPHER_LIST_TLSv13[TLSv13len - 1] == ':') { + CLIENT_CIPHER_LIST_TLSv13[TLSv13len - 1] = '\0'; + } + + const bool tls12_ciphers_ok = SSL_set_cipher_list( + result->ssl, + isServer ? UNRESTRICTED_TLS1_2_SERVER_CIPHER_LIST : CLIENT_CIPHER_LIST); + + bool tls13_ciphers_ok = true; +#ifdef HAVE_SSL_SET_CIPHERSUITES + if (!isServer) { + tls13_ciphers_ok = + SSL_set_ciphersuites(result->ssl, CLIENT_CIPHER_LIST_TLSv13); + } +#endif + + if (!tls12_ciphers_ok || !tls13_ciphers_ok) { tls_log_errors(NULL, LOG_WARN, LD_NET, "setting ciphers"); #ifdef SSL_set_tlsext_host_name SSL_set_tlsext_host_name(result->ssl, NULL); @@ -1104,6 +703,7 @@ tor_free(result); goto err; } + result->socket = sock; bio = BIO_new_socket(sock, BIO_CLOSE); if (! bio) { @@ -1135,14 +735,8 @@ log_warn(LD_NET, "Newly created BIO has read count %lu, write count %lu", result->last_read_count, result->last_write_count); } - if (isServer) { - SSL_set_info_callback(result->ssl, tor_tls_server_info_callback); - } else { - SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback); - } - if (isServer) - tor_tls_setup_session_secret_cb(result); + SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback); goto done; err: @@ -1153,51 +747,6 @@ return result; } -/** Set cb to be called with argument arg whenever tls - * next gets a client-side renegotiate in the middle of a read. Do not - * invoke this function until after initial handshaking is done! - */ -void -tor_tls_set_renegotiate_callback(tor_tls_t *tls, - void (*cb)(tor_tls_t *, void *arg), - void *arg) -{ - tls->negotiated_callback = cb; - tls->callback_arg = arg; - tls->got_renegotiate = 0; - if (cb) { - SSL_set_info_callback(tls->ssl, tor_tls_server_info_callback); - } else { - SSL_set_info_callback(tls->ssl, tor_tls_debug_state_callback); - } -} - -/** If this version of openssl requires it, turn on renegotiation on - * tls. - */ -void -tor_tls_unblock_renegotiation(tor_tls_t *tls) -{ - /* Yes, we know what we are doing here. No, we do not treat a renegotiation - * as authenticating any earlier-received data. */ - SSL_set_options(tls->ssl, - SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION); -} - -/** If this version of openssl supports it, turn off renegotiation on - * tls. (Our protocol never requires this for security, but it's nice - * to use belt-and-suspenders here.) - */ -void -tor_tls_block_renegotiation(tor_tls_t *tls) -{ -#ifdef SUPPORT_UNSAFE_RENEGOTIATION_FLAG - tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; -#else - (void) tls; -#endif -} - /** * Tell the TLS library that the underlying socket for tls has been * closed, and the library should not attempt to free that socket itself. @@ -1247,13 +796,6 @@ tor_assert(lenssl, cp, (int)len); if (r > 0) { - if (tls->got_renegotiate) { - /* Renegotiation happened! */ - log_info(LD_NET, "Got a TLS renegotiation from %s", ADDR(tls)); - if (tls->negotiated_callback) - tls->negotiated_callback(tls, tls->callback_arg); - tls->got_renegotiate = 0; - } return r; } err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET); @@ -1341,9 +883,7 @@ if (oldstate != newstate) log_debug(LD_HANDSHAKE, "After call, %p was in state %s", tls, SSL_state_string_long(tls->ssl)); - /* We need to call this here and not earlier, since OpenSSL has a penchant - * for clearing its flags when you say accept or connect. */ - tor_tls_unblock_renegotiation(tls); + r = tor_tls_get_error(tls,r,0, "handshaking", LOG_INFO, LD_HANDSHAKE); if (ERR_peek_error() != 0) { tls_log_errors(tls, tls->isServer ? LOG_INFO : LOG_WARN, LD_HANDSHAKE, @@ -1352,52 +892,7 @@ } if (r == TOR_TLS_DONE) { tls->state = TOR_TLS_ST_OPEN; - return tor_tls_finish_handshake(tls); - } - return r; -} - -/** Perform the final part of the initial TLS handshake on tls. This - * should be called for the first handshake only: it determines whether the v1 - * or the v2 handshake was used, and adjusts things for the renegotiation - * handshake as appropriate. - * - * tor_tls_handshake() calls this on its own; you only need to call this if - * bufferevent is doing the handshake for you. - */ -int -tor_tls_finish_handshake(tor_tls_t *tls) -{ - int r = TOR_TLS_DONE; - check_no_tls_errors(); - if (tls->isServer) { - SSL_set_info_callback(tls->ssl, NULL); - SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb); - SSL_clear_mode(tls->ssl, SSL_MODE_NO_AUTO_CHAIN); - if (tor_tls_client_is_using_v2_ciphers(tls->ssl)) { - /* This check is redundant, but back when we did it in the callback, - * we might have not been able to look up the tor_tls_t if the code - * was buggy. Fixing that. */ - if (!tls->wasV2Handshake) { - log_warn(LD_BUG, "For some reason, wasV2Handshake didn't" - " get set. Fixing that."); - } - tls->wasV2Handshake = 1; - log_debug(LD_HANDSHAKE, "Completed V2 TLS handshake with client; waiting" - " for renegotiation."); - } else { - tls->wasV2Handshake = 0; - } - } else { - /* Client-side */ - tls->wasV2Handshake = 1; - /* XXXX this can move, probably? -NM */ - if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) { - tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers"); - r = TOR_TLS_ERROR_MISC; - } } - tls_log_errors(NULL, LOG_WARN, LD_NET, "finishing the handshake"); return r; } @@ -1446,44 +941,6 @@ return tor_x509_cert_new(duplicate); } -/** Helper function: try to extract a link certificate and an identity - * certificate from tls, and store them in *cert_out and - * *id_cert_out respectively. Log all messages at level - * severity. - * - * Note that a reference is added both of the returned certificates. */ -MOCK_IMPL(void, -try_to_extract_certs_from_tls,(int severity, tor_tls_t *tls, - X509 **cert_out, X509 **id_cert_out)) -{ - X509 *cert = NULL, *id_cert = NULL; - STACK_OF(X509) *chain = NULL; - int num_in_chain, i; - *cert_out = *id_cert_out = NULL; - if (!(cert = SSL_get_peer_certificate(tls->ssl))) - return; - *cert_out = cert; - if (!(chain = SSL_get_peer_cert_chain(tls->ssl))) - return; - num_in_chain = sk_X509_num(chain); - /* 1 means we're receiving (server-side), and it's just the id_cert. - * 2 means we're connecting (client-side), and it's both the link - * cert and the id_cert. - */ - if (num_in_chain < 1) { - log_fn(severity,LD_PROTOCOL, - "Unexpected number of certificates in chain (%d)", - num_in_chain); - return; - } - for (i=0; itls. */ int @@ -1518,18 +975,9 @@ * save the original BIO for tls->ssl in the tor_tls_t structure, but * that would be tempting fate. */ wbio = SSL_get_wbio(tls->ssl); -#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) - /* BIO structure is opaque as of OpenSSL 1.1.0-pre5-dev. Again, not - * supposed to use this form of the version macro, but the OpenSSL developers - * introduced major API changes in the pre-release stage. - */ if (BIO_method_type(wbio) == BIO_TYPE_BUFFER && (tmpbio = BIO_next(wbio)) != NULL) wbio = tmpbio; -#else /* !(OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5)) */ - if (wbio->method == BIO_f_buffer() && (tmpbio = BIO_next(wbio)) != NULL) - wbio = tmpbio; -#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) */ w = (unsigned long) BIO_number_written(wbio); /* We are ok with letting these unsigned ints go "negative" here: @@ -1573,153 +1021,6 @@ tls_log_errors(NULL, LOG_WARN, LD_NET, NULL); } -/** Return true iff the initial TLS connection at tls did not use a v2 - * TLS handshake. Output is undefined if the handshake isn't finished. */ -int -tor_tls_used_v1_handshake(tor_tls_t *tls) -{ - return ! tls->wasV2Handshake; -} - -/** Return true iff the server TLS connection tls got the renegotiation - * request it was waiting for. */ -int -tor_tls_server_got_renegotiate(tor_tls_t *tls) -{ - return tls->got_renegotiate; -} - -#ifndef HAVE_SSL_GET_CLIENT_RANDOM -static size_t -SSL_get_client_random(SSL *s, uint8_t *out, size_t len) -{ - if (len == 0) - return SSL3_RANDOM_SIZE; - tor_assert(len == SSL3_RANDOM_SIZE); - tor_assert(s->s3); - memcpy(out, s->s3->client_random, len); - return len; -} -#endif /* !defined(HAVE_SSL_GET_CLIENT_RANDOM) */ - -#ifndef HAVE_SSL_GET_SERVER_RANDOM -static size_t -SSL_get_server_random(SSL *s, uint8_t *out, size_t len) -{ - if (len == 0) - return SSL3_RANDOM_SIZE; - tor_assert(len == SSL3_RANDOM_SIZE); - tor_assert(s->s3); - memcpy(out, s->s3->server_random, len); - return len; -} -#endif /* !defined(HAVE_SSL_GET_SERVER_RANDOM) */ - -#ifndef HAVE_SSL_SESSION_GET_MASTER_KEY -size_t -SSL_SESSION_get_master_key(SSL_SESSION *s, uint8_t *out, size_t len) -{ - tor_assert(s); - if (len == 0) - return s->master_key_length; - tor_assert(len == (size_t)s->master_key_length); - tor_assert(out); - memcpy(out, s->master_key, len); - return len; -} -#endif /* !defined(HAVE_SSL_SESSION_GET_MASTER_KEY) */ - -/** Set the DIGEST256_LEN buffer at secrets_out to the value used in - * the v3 handshake to prove that the client knows the TLS secrets for the - * connection tls. Return 0 on success, -1 on failure. - */ -MOCK_IMPL(int, -tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out)) -{ -#define TLSSECRET_MAGIC "Tor V3 handshake TLS cross-certification" - uint8_t buf[128]; - size_t len; - tor_assert(tls); - - SSL *const ssl = tls->ssl; - SSL_SESSION *const session = SSL_get_session(ssl); - - tor_assert(ssl); - tor_assert(session); - - const size_t server_random_len = SSL_get_server_random(ssl, NULL, 0); - const size_t client_random_len = SSL_get_client_random(ssl, NULL, 0); - const size_t master_key_len = SSL_SESSION_get_master_key(session, NULL, 0); - - if (BUG(! server_random_len)) { - log_warn(LD_NET, "Missing server randomness after handshake " - "using %s (cipher: %s, server: %s) from %s", - SSL_get_version(ssl), - SSL_get_cipher_name(ssl), - tls->isServer ? "true" : "false", - ADDR(tls)); - return -1; - } - - if (BUG(! client_random_len)) { - log_warn(LD_NET, "Missing client randomness after handshake " - "using %s (cipher: %s, server: %s) from %s", - SSL_get_version(ssl), - SSL_get_cipher_name(ssl), - tls->isServer ? "true" : "false", - ADDR(tls)); - return -1; - } - - if (BUG(! master_key_len)) { - log_warn(LD_NET, "Missing master key after handshake " - "using %s (cipher: %s, server: %s) from %s", - SSL_get_version(ssl), - SSL_get_cipher_name(ssl), - tls->isServer ? "true" : "false", - ADDR(tls)); - return -1; - } - - len = client_random_len + server_random_len + strlen(TLSSECRET_MAGIC) + 1; - tor_assert(len <= sizeof(buf)); - - { - size_t r = SSL_get_client_random(ssl, buf, client_random_len); - tor_assert(r == client_random_len); - } - - { - size_t r = SSL_get_server_random(ssl, - buf+client_random_len, - server_random_len); - tor_assert(r == server_random_len); - } - - uint8_t *master_key = tor_malloc_zero(master_key_len); - { - size_t r = SSL_SESSION_get_master_key(session, master_key, master_key_len); - tor_assert(r == master_key_len); - } - - uint8_t *nextbuf = buf + client_random_len + server_random_len; - memcpy(nextbuf, TLSSECRET_MAGIC, strlen(TLSSECRET_MAGIC) + 1); - - /* - The value is an HMAC, using the TLS master key as the HMAC key, of - client_random | server_random | TLSSECRET_MAGIC - */ - crypto_hmac_sha256((char*)secrets_out, - (char*)master_key, - master_key_len, - (char*)buf, len); - memwipe(buf, 0, sizeof(buf)); - memwipe(master_key, 0, master_key_len); - tor_free(master_key); - - return 0; -} - /** Using the RFC5705 key material exporting construction, and the * provided context (context_len bytes long) and * label (a NUL-terminated string), compute a 32-byte secret in @@ -1787,7 +1088,6 @@ size_t *rbuf_capacity, size_t *rbuf_bytes, size_t *wbuf_capacity, size_t *wbuf_bytes) { -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) (void)tls; (void)rbuf_capacity; (void)rbuf_bytes; @@ -1795,19 +1095,6 @@ (void)wbuf_bytes; return -1; -#else /* !(OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0)) */ - if (tls->ssl->s3->rbuf.buf) - *rbuf_capacity = tls->ssl->s3->rbuf.len; - else - *rbuf_capacity = 0; - if (tls->ssl->s3->wbuf.buf) - *wbuf_capacity = tls->ssl->s3->wbuf.len; - else - *wbuf_capacity = 0; - *rbuf_bytes = tls->ssl->s3->rbuf.left; - *wbuf_bytes = tls->ssl->s3->wbuf.left; - return 0; -#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) */ } /** Check whether the ECC group requested is supported by the current OpenSSL diff -Nru tor-0.4.8.16/src/lib/tls/tortls_st.h tor-0.4.9.6/src/lib/tls/tortls_st.h --- tor-0.4.8.16/src/lib/tls/tortls_st.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/tls/tortls_st.h 2026-03-25 14:30:34.000000000 +0000 @@ -49,17 +49,7 @@ * depending on which operations * have completed successfully. */ unsigned int isServer:1; /**< True iff this is a server-side connection */ - unsigned int wasV2Handshake:1; /**< True iff the original handshake for - * this connection used the updated version - * of the connection protocol (client sends - * different cipher list, server sends only - * one certificate). */ - /** True iff we should call negotiated_callback when we're done reading. */ - unsigned int got_renegotiate:1; #ifdef ENABLE_OPENSSL - /** Return value from tor_tls_classify_client_ciphers, or 0 if we haven't - * called that function yet. */ - int8_t client_cipher_list_type; size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last * time. */ /** Last values retrieved from BIO_number_read()/write(); see diff -Nru tor-0.4.8.16/src/lib/tls/x509_openssl.c tor-0.4.9.6/src/lib/tls/x509_openssl.c --- tor-0.4.8.16/src/lib/tls/x509_openssl.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/lib/tls/x509_openssl.c 2026-03-25 14:30:34.000000000 +0000 @@ -46,7 +46,6 @@ #include #include -#ifdef OPENSSL_1_1_API #define X509_get_notBefore_const(cert) \ X509_get0_notBefore(cert) #define X509_get_notAfter_const(cert) \ @@ -59,12 +58,6 @@ #define X509_get_notAfter(cert) \ X509_getm_notAfter(cert) #endif -#else /* !defined(OPENSSL_1_1_API) */ -#define X509_get_notBefore_const(cert) \ - ((const ASN1_TIME*) X509_get_notBefore((X509 *)cert)) -#define X509_get_notAfter_const(cert) \ - ((const ASN1_TIME*) X509_get_notAfter((X509 *)cert)) -#endif /* defined(OPENSSL_1_1_API) */ /** Return a newly allocated X509 name with commonName cname. */ static X509_NAME * @@ -329,11 +322,7 @@ cert_key = X509_get_pubkey(cert->cert); if (check_rsa_1024 && cert_key) { RSA *rsa = EVP_PKEY_get1_RSA(cert_key); -#ifdef OPENSSL_1_1_API if (rsa && RSA_bits(rsa) == 1024) { -#else - if (rsa && BN_num_bits(rsa->n) == 1024) { -#endif key_ok = 1; } else { log_fn(severity, LD_CRYPTO, "Invalid certificate: Key is not RSA1024."); diff -Nru tor-0.4.8.16/src/test/bench.c tor-0.4.9.6/src/test/bench.c --- tor-0.4.8.16/src/test/bench.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/bench.c 2026-03-25 14:30:34.000000000 +0000 @@ -11,7 +11,6 @@ #include "orconfig.h" #include "core/or/or.h" -#include "core/crypto/onion_tap.h" #include "core/crypto/relay_crypto.h" #include "lib/intmath/weakrng.h" @@ -24,6 +23,9 @@ #include #endif /* defined(ENABLE_OPENSSL) */ +#include + +#include "ext/polyval/polyval.h" #include "core/or/circuitlist.h" #include "app/config/config.h" #include "app/main/subsysmgr.h" @@ -34,6 +36,7 @@ #include "lib/crypt_ops/crypto_rand.h" #include "feature/dircommon/consdiff.h" #include "lib/compress/compress.h" +#include "core/crypto/relay_crypto_cgo.h" #include "core/or/cell_st.h" #include "core/or/or_circuit_st.h" @@ -44,6 +47,27 @@ #include "feature/dirparse/microdesc_parse.h" #include "feature/nodelist/microdesc.h" +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) \ + || defined(_M_X64) || defined(_M_IX86) || defined(__i486) \ + || defined(__i386__) +#define INTEL +#endif + +#ifdef INTEL +#include "x86intrin.h" + +static inline uint64_t +cycles(void) +{ + return __rdtsc(); +} +#define cpb(start, end, bytes) \ + (((double)(end - start)) / (bytes)) +#else +#define cycles() 0 +#define cpb(start,end,bytes) ((void)(start+end+bytes), (double)NAN) +#endif + #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) static uint64_t nanostart; static inline uint64_t @@ -127,75 +151,6 @@ } static void -bench_onion_TAP(void) -{ - const int iters = 1<<9; - int i; - crypto_pk_t *key, *key2; - uint64_t start, end; - char os[TAP_ONIONSKIN_CHALLENGE_LEN]; - char or[TAP_ONIONSKIN_REPLY_LEN]; - crypto_dh_t *dh_out = NULL; - - key = crypto_pk_new(); - key2 = crypto_pk_new(); - if (crypto_pk_generate_key_with_bits(key, 1024) < 0) - goto done; - if (crypto_pk_generate_key_with_bits(key2, 1024) < 0) - goto done; - - reset_perftime(); - start = perftime(); - for (i = 0; i < iters; ++i) { - onion_skin_TAP_create(key, &dh_out, os); - crypto_dh_free(dh_out); - } - end = perftime(); - printf("Client-side, part 1: %f usec.\n", NANOCOUNT(start, end, iters)/1e3); - - onion_skin_TAP_create(key, &dh_out, os); - start = perftime(); - for (i = 0; i < iters; ++i) { - char key_out[CPATH_KEY_MATERIAL_LEN]; - onion_skin_TAP_server_handshake(os, key, NULL, or, - key_out, sizeof(key_out)); - } - end = perftime(); - printf("Server-side, key guessed right: %f usec\n", - NANOCOUNT(start, end, iters)/1e3); - - start = perftime(); - for (i = 0; i < iters; ++i) { - char key_out[CPATH_KEY_MATERIAL_LEN]; - onion_skin_TAP_server_handshake(os, key2, key, or, - key_out, sizeof(key_out)); - } - end = perftime(); - printf("Server-side, key guessed wrong: %f usec.\n", - NANOCOUNT(start, end, iters)/1e3); - - start = perftime(); - for (i = 0; i < iters; ++i) { - crypto_dh_t *dh; - char key_out[CPATH_KEY_MATERIAL_LEN]; - int s; - dh = crypto_dh_dup(dh_out); - s = onion_skin_TAP_client_handshake(dh, or, key_out, sizeof(key_out), - NULL); - crypto_dh_free(dh); - tor_assert(s == 0); - } - end = perftime(); - printf("Client-side, part 2: %f usec.\n", - NANOCOUNT(start, end, iters)/1e3); - - done: - crypto_dh_free(dh_out); - crypto_pk_free(key); - crypto_pk_free(key2); -} - -static void bench_onion_ntor_impl(void) { const int iters = 1<<10; @@ -568,9 +523,9 @@ } static void -bench_cell_ops(void) +bench_cell_ops_tor1(void) { - const int iters = 1<<16; + const int iters = 1<<20; int i; /* benchmarks for cell ops at relay. */ @@ -578,6 +533,10 @@ cell_t *cell = tor_malloc(sizeof(cell_t)); int outbound; uint64_t start, end; + uint64_t cstart, cend; + + // TODO CGO: use constant after this is merged or rebased. + const unsigned payload_len = 498; crypto_rand((char*)cell->payload, sizeof(cell->payload)); @@ -586,31 +545,46 @@ or_circ->base_.purpose = CIRCUIT_PURPOSE_OR; /* Initialize crypto */ - char key1[CIPHER_KEY_LEN], key2[CIPHER_KEY_LEN]; - crypto_rand(key1, sizeof(key1)); - crypto_rand(key2, sizeof(key2)); - or_circ->crypto.f_crypto = crypto_cipher_new(key1); - or_circ->crypto.b_crypto = crypto_cipher_new(key2); - or_circ->crypto.f_digest = crypto_digest_new(); - or_circ->crypto.b_digest = crypto_digest_new(); + char keys[CPATH_KEY_MATERIAL_LEN]; + crypto_rand(keys, sizeof(keys)); + size_t keylen = sizeof(keys); + relay_crypto_init(RELAY_CRYPTO_ALG_TOR1, + &or_circ->crypto, keys, keylen); reset_perftime(); for (outbound = 0; outbound <= 1; ++outbound) { cell_direction_t d = outbound ? CELL_DIRECTION_OUT : CELL_DIRECTION_IN; start = perftime(); + cstart = cycles(); for (i = 0; i < iters; ++i) { char recognized = 0; crypt_path_t *layer_hint = NULL; relay_decrypt_cell(TO_CIRCUIT(or_circ), cell, d, &layer_hint, &recognized); } + cend = cycles(); end = perftime(); - printf("%sbound cells: %.2f ns per cell. (%.2f ns per byte of payload)\n", + printf("%sbound cells: %.2f ns per cell. " + "(%.2f ns per byte of payload, %.2f cpb)\n", outbound?"Out":" In", NANOCOUNT(start,end,iters), - NANOCOUNT(start,end,iters*CELL_PAYLOAD_SIZE)); + NANOCOUNT(start,end,iters * payload_len), + cpb(cstart, cend, iters * payload_len)); + } + + start = perftime(); + cstart = cycles(); + for (i = 0; i < iters; ++i) { + relay_encrypt_cell_inbound(cell, or_circ); } + cend = cycles(); + end = perftime(); + printf("originate inbound : %.2f ns per cell. " + "(%.2f ns per payload byte, %.2f cpb)\n", + NANOCOUNT(start, end, iters), + NANOCOUNT(start, end, iters * payload_len), + cpb(cstart, cend, iters*payload_len)); relay_crypto_clear(&or_circ->crypto); tor_free(or_circ); @@ -618,6 +592,126 @@ } static void +bench_polyval(void) +{ + polyval_t pv; + polyvalx_t pvx; + uint8_t key[16]; + uint8_t input[512]; + uint64_t start, end, cstart, cend; + crypto_rand((char*) key, sizeof(key)); + crypto_rand((char*) input, sizeof(input)); + + const int iters = 1<<20; + + polyval_init(&pv, key); + start = perftime(); + cstart = cycles(); + for (int i = 0; i < iters; ++i) { + polyval_add_block(&pv, input); + } + cend = cycles(); + end = perftime(); + printf("polyval (add 16): %.2f ns; %.2f cpb\n", + NANOCOUNT(start, end, iters), + cpb(cstart, cend, iters * 16)); + + start = perftime(); + cstart = cycles(); + for (int i = 0; i < iters; ++i) { + polyval_add_zpad(&pv, input, 512); + } + cend = cycles(); + end = perftime(); + printf("polyval (add 512): %.2f ns; %.2f cpb\n", + NANOCOUNT(start, end, iters), + cpb(cstart, cend, iters * 512)); + + polyvalx_init(&pvx, key); + start = perftime(); + cstart = cycles(); + for (int i = 0; i < iters; ++i) { + polyvalx_add_zpad(&pvx, input, 512); + } + cend = cycles(); + end = perftime(); + printf("polyval (add 512, pre-expanded key): %.2f ns; %.2f cpb\n", + NANOCOUNT(start, end, iters), + cpb(cstart, cend, iters * 512)); +} + +static void +bench_cell_ops_cgo(void) +{ + const int iters = 1<<20; + + /* benchmarks for cell ops at relay. */ + cell_t *cell = tor_malloc(sizeof(cell_t)); + + uint64_t start, end; + uint64_t cstart, cend; + + const uint8_t *tag = NULL; + size_t keylen = cgo_key_material_len(128); + uint8_t *keys = tor_malloc(keylen); + crypto_rand((char*) keys, keylen); + + // We're using the version of this constant that _does_ include + // stream IDs, for an apples-to-apples comparison with tor1. + // + // TODO CGO: use constant after this is merged or rebased. + const unsigned payload_len = 488; + + memset(cell, 0, sizeof(*cell)); + +#define SHOW(operation) \ + printf("%s: %.2f per cell (%.2f cpb)\n", \ + (operation), \ + NANOCOUNT(start,end,iters), \ + cpb(cstart, cend, (double)iters * payload_len)) + + // Initialize crypto + cgo_crypt_t *r_f = cgo_crypt_new(CGO_MODE_RELAY_FORWARD, 128, keys, keylen); + cgo_crypt_t *r_b = cgo_crypt_new(CGO_MODE_RELAY_BACKWARD, 128, keys, keylen); + + reset_perftime(); + + start = perftime(); + cstart = cycles(); + for (int i=0; i < iters; ++i) { + cgo_crypt_relay_forward(r_f, cell, &tag); + } + cend = cycles(); + end = perftime(); + SHOW("CGO outbound at relay"); + + start = perftime(); + cstart = cycles(); + for (int i=0; i < iters; ++i) { + cgo_crypt_relay_backward(r_b, cell); + } + cend = cycles(); + end = perftime(); + SHOW("CGO inbound at relay"); + + start = perftime(); + cstart = cycles(); + for (int i=0; i < iters; ++i) { + cgo_crypt_relay_originate(r_b, cell, &tag); + } + cend = cycles(); + end = perftime(); + SHOW("CGO originate at relay"); + + tor_free(cell); + tor_free(keys); + cgo_crypt_free(r_f); + cgo_crypt_free(r_b); + +#undef SHOW +} + +static void bench_dh(void) { const int iters = 1<<10; @@ -753,14 +847,15 @@ ENT(dmap), ENT(siphash), ENT(digest), + ENT(polyval), ENT(aes), - ENT(onion_TAP), ENT(onion_ntor), ENT(ed25519), ENT(rand), ENT(cell_aes), - ENT(cell_ops), + ENT(cell_ops_tor1), + ENT(cell_ops_cgo), ENT(dh), #ifdef ENABLE_OPENSSL diff -Nru tor-0.4.8.16/src/test/cgo_vectors.inc tor-0.4.9.6/src/test/cgo_vectors.inc --- tor-0.4.8.16/src/test/cgo_vectors.inc 1970-01-01 00:00:00.000000000 +0000 +++ tor-0.4.9.6/src/test/cgo_vectors.inc 2026-03-25 14:30:34.000000000 +0000 @@ -0,0 +1,651 @@ +/* CGO test vectors. Chosen from those generated by + * the python reference implementation. + */ + +/* Accept python booleans here. */ +#define True true +#define False false + +static const struct et_testvec { + bool encrypt; + const char *keys; + const char *tweaks; + const char *block; + const char *expect; +} ET_TESTVECS[] = { +// Zeroes, encrypt +{ + // Encrypt + True, + // (KB,KU) + "0000000000000000000000000000000000000000000000000000000000000000", + // T + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // M + "00000000000000000000000000000000", + // OUTPUT + "66e94bd4ef8a2c3b884cfa59ca342b2e", +}, +// Zeroes, decrypt +{ + // Encrypt + False, + // (KB,KU) + "0000000000000000000000000000000000000000000000000000000000000000", + // T + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // M + "00000000000000000000000000000000", + // OUTPUT + "140f0f1011b5223d79587717ffd9ec3a", +}, +// Pseudorandom 1, Encrypt +{ + // Encrypt + True, + // (KB,KU) + "39dd87e0b958cec5d2ba04a17fad9f134770f20f14038bdcd751056a7f16041f", + // T + "fbf69df9bfc3bec7e4a5dd0c9785dd18727dab2b11baf2898b3b775baed777d209812a71e8d5a1f624a4c2c3ccd91064f494f5deb2b7ab362cda53df3e0291cc439052a05cdbc8fe259f7190792b637eeaf0c5ebdf7d02ec6b89beecf131a916f5c6989267e28defaa5937b35f0a1ce1ef91838c408b2d199170f29e76ae21b8b62a733e4de9d281e6935d20d991e3e1801907f6477f9fd40bd4e72de681336e603bb7ec17d512728864b7cebc9bc6bbc0629082830fa3702cb2eff0fb289b7431d4e1b0b6109599c91c4c78540792331e592fe8c0c190ea18275386ec3d85f68996b6891e484ad4b0601008ead6ed60145f8d01b81d1cf31556744b1676f6c5caea56c5cd424350e0bc3c478efc2e11d868ddf73185627c778ba8b7d684f3d0b9dfe7e1b63985bb43e37a2e5938cae8b1741cb58aea2b383de9bf0531e344a5651f7f145aad1656e695e30ee6483b5e18e43b0aa6e308f2e1c8cfdd85a118476c9ca91c8ca993563b2df014289738c4b6ce772e2ac36a26547b97ba26673e28e634f88a91007e220f1beaa97ae00972954fc705de30642014fa5c4c07792a0f0b4a8ef3c6f0584b1029171a28cd5898e760c91f71c5f9610747ae21f30f1b1bfa7e4df9aedfa8b006f29e89e5b182ac9957067f86767ed5620abcb2c50a41c423e48a676864a2d151c5bf2442f3b90bfd7c047f92cd112367d0579c9f02", + // M + "40f417ba5a4c78a23e6540b52b68e1e6", + // OUTPUT + "84bfff8347889f1a9f2cf930c82677be", +}, +// Pseudorandom 1, Decrypt +{ + // Encrypt + False, + // (KB,KU) + "39dd87e0b958cec5d2ba04a17fad9f134770f20f14038bdcd751056a7f16041f", + // T + "fbf69df9bfc3bec7e4a5dd0c9785dd18727dab2b11baf2898b3b775baed777d209812a71e8d5a1f624a4c2c3ccd91064f494f5deb2b7ab362cda53df3e0291cc439052a05cdbc8fe259f7190792b637eeaf0c5ebdf7d02ec6b89beecf131a916f5c6989267e28defaa5937b35f0a1ce1ef91838c408b2d199170f29e76ae21b8b62a733e4de9d281e6935d20d991e3e1801907f6477f9fd40bd4e72de681336e603bb7ec17d512728864b7cebc9bc6bbc0629082830fa3702cb2eff0fb289b7431d4e1b0b6109599c91c4c78540792331e592fe8c0c190ea18275386ec3d85f68996b6891e484ad4b0601008ead6ed60145f8d01b81d1cf31556744b1676f6c5caea56c5cd424350e0bc3c478efc2e11d868ddf73185627c778ba8b7d684f3d0b9dfe7e1b63985bb43e37a2e5938cae8b1741cb58aea2b383de9bf0531e344a5651f7f145aad1656e695e30ee6483b5e18e43b0aa6e308f2e1c8cfdd85a118476c9ca91c8ca993563b2df014289738c4b6ce772e2ac36a26547b97ba26673e28e634f88a91007e220f1beaa97ae00972954fc705de30642014fa5c4c07792a0f0b4a8ef3c6f0584b1029171a28cd5898e760c91f71c5f9610747ae21f30f1b1bfa7e4df9aedfa8b006f29e89e5b182ac9957067f86767ed5620abcb2c50a41c423e48a676864a2d151c5bf2442f3b90bfd7c047f92cd112367d0579c9f02", + // M + "40f417ba5a4c78a23e6540b52b68e1e6", + // OUTPUT + "e2c0bfdef28b5504cf0ec708a6866a17", +}}; + +static const struct prf_testvec { + const char *keys; + int t; + const char *input; + const char *expect; +} PRF_TESTVECS[] = { +// All zeros, t=0 +{ + // K,B + "0000000000000000000000000000000000000000000000000000000000000000", + // T + 0, + // t + "00000000000000000000000000000000", + // OUTPUT + "66e94bd4ef8a2c3b884cfa59ca342b2e58e2fccefa7e3061367f1d57a4e7455a0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40deb3fa6794f8fd8f55a88dcbda9d68f2137cc9c83420077e7cf28ab2696b0df05d11452b58ac50aa2eb3a195b61b87e5c65a6dd5d7f7a84065d5a17ff46273086002496db63fa4b91bee387fa3030c95a73f8d0437e0915fbce5d7a62d8dab0a58b2431bc0bede02550f40238969ec780410befccde6944b69dd007debe39a9dbc5e24f519a4bdf478b1d9ec0b67125f28b06efaa55d79412ad628d45089c3c304f94db3a21df6cdaf6d2e2e3b355441eff64ad90527e752a4b2ebb4d0a1070ce2e2982e272fdb7cf4b584b095a0f957fdb828689437e37dc48b2ad379c6f3c6e957ee77afb88c65949ba12eec45c22865e4907ae42aee813898acdf91e2e4c21d828e0a76de2bb6bb6f869e5eef1f618dedd27562812b9a14e8996a5c352df3817e60d6ec20119a52c80a61ec195622627240212decca515feab63e2734587948a836a7de205cfec0c288351c", +}, +// All zeros, t=1 +{ + // K,B + "0000000000000000000000000000000000000000000000000000000000000000", + // T + 1, + // t + "00000000000000000000000000000000", + // OUTPUT + "7941dd0a63d994703e63d94a446804213ab4fb1d2b7ba376590a2c241d1f508dc6a7f418a14503deb89b17aadb2806f73fc06e5d14e675f5ec880023d4f7329612dce4a0e5bc792b5b5a55f9c2f30e07", +}, +// All ones, t=0 +{ + // K,B + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + // T + 0, + // t + "ffffffffffffffffffffffffffffffff", + // OUTPUT + "3ae902931ae8d3ba07a2efdbf0411525c966356463673443646d3ed3e5ba68a61ccd8ae0d8f8d84adca5c0023f02efd10cc7bc7c9fbfd169bf47a792bbba07d6c9338101d0c28e476e99520413a37c3c9045909a8d37c6cba7f9e33254ff0b2ea11ccd6d0a6eed028bb3acccb38fe0a50ea2ca51dc35dc12541f5ce00611336ef966d9a9027a6342c09590d056880e79bfd1a271aff821114649e33a6b4d83be0883b3ad4b315ac6b77017c748a8bb71a981678ff9c6ca086507efb6e8850043767bea06d66ee5e9b2870107474150044488a2d00bd1d5154e0f1aeac5af0b73049004f8717baa13c1ae0088f2dfdf8e08a612aa11a8bb64ab2a4d292967504a6cb451a56275b756c2d7f65aab728617154693a7b31d048802b0ce635754977fb851bb21dddcd9564795e31523fcc35ccfc066b9542508b4daa65b4c9083b12a5cd08f7c45906523d5d7131f279959900473a756e48ababa93fb42663401d84bef93c6cfd6e02fc17797a7004671d21d3bc35cb2e9a344da0a16c300f3c977b6c892e0c2a9517862bec47a51fd49c5a4d46620ea5df9a055e89c2d54abffb00704c1219175433bc1683d93c75ffd7feccc605092b197c5aa5aa995ba0c0e33870b0f513a5eefd9d64fc6e89862709ca9876df86c189181e70e4eed2d876a12480b64afaffe54ba4ac8f23043d8", +}, +// All ones, t=1 +{ + // K,B + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + // T + 1, + // t + "ffffffffffffffffffffffffffffffff", + // OUTPUT + "be938fc23009440bfb5d7bba1d28428ec0897793bb878b8e1eb3ec1257b88024d551d770b56c9312de3dd4ac64e194c91185a89f2ba01f90b03b3acb93f634df4b263f03af0acda2f9721d0f4c0783c7", +}, +// Pseudorandom 1, t=0 +{ + // K,B + "908bf9a158c67f9cd5cb5cee476a4b30b9ec92756d94b1f9f40073c185c39780", + // T + 0, + // t + "d5d73799a0f37a1c7ff3ceb187ebd059", + // OUTPUT + "0573c27e297dad58e84942c498d3c376c1f8423dea1df70338259814f2b939ffe074b22fae1385e2d453aca882cb6257ec4fc86915f05be11ae36df4d8678ff29f68c45797c2a4158c4c30c703faeda452858ae37b7735f47b2924cd6f6040e7f6b19958f6d5a12aae72b589d6f85e5a3267881b2916da948fe1626d68ee60a13c90599b40f8a14fd8d1354bc5beb23f38043d7e547b879f618302426dd7785bc2caf44b31a2e1ec5d4dcb4047415d0bbc6900dfdfa01e61c4aa3624f6d7f03cc1641610bd0d6f155cae7465a3d1e0ae8db7d5a00afd27824fd35b65a91728981566c7a046f1773210b76a449b76b5684eb3532a06225d89b70aae1d20c27d03c528b00051a3eb74f3b217b3d474076b8c4bab837476c6191bc7ae8266328d5a65f6a2c55c30999984e2747b7dc45af9e43533b750d9196cd2d64947b6dcf839821002441a428bbbeee45de052502aa76385b47aedbdbeed500c359fdd1ba042a5c9956a1b2e3e456472665f7a674d898a9c5ee58e6288304a323986f0d09b731ae401ac5f8ebeaf808cecce9945439ec76cccb5aafb875faf1274bc29beb29413e01ef72cb37eebc06428c24221f8af3c5ea742fc41506d501d8e45bed5d982ab16669da486c985a3e140eb55c754aaf3d7923d76519f8bac02e0e0c0961411d8c010d1c58498caeae8c69c62", +}, +// Pseudorandom 1, t=1 +{ + // K,B + "908bf9a158c67f9cd5cb5cee476a4b30b9ec92756d94b1f9f40073c185c39780", + // T + 1, + // t + "d5d73799a0f37a1c7ff3ceb187ebd059", + // OUTPUT + "75c5c6787bd0edf325cf772b8c09478df5094f093eddda9d4b7c2ab4ebcdd84c87192038ade81b8560ef7f5a3eb89a4957cf9bd138c575b6951f9940d44d443f47616dfdaf73be7a4664aa46bc279c20", +}, +// Pseudorandom 2, t=0 +{ + // K,B + "fcd9361d1dca1c7b9a24f754464eeda5727152bc98a818b2e720a0afa9103e10", + // T + 0, + // t + "d22ea954482f5bc511c6fcae80233d57", + // OUTPUT + "e5be8144283c5b638a7bbcae231cfb9d6727ee8f04bcf0f3c7ff94930facee8030712bc8b0d151a5ea27c4f614cd46fe1ef9eee2f64c8d8ddfce7ab1ed01cdd610e7b341b75408a6a8310ed62389348b76a59277a0eee05bdd5f5227d43fc113294b3af71d505a0c88d920387f44ef33029797d0c282991683adca83449e68aff578df836ee6b89cfc5fb0e8ce0d8d5146a09d57ec816e0fbbbdf80b298dfe6509aefcc892a6dd4bbbbfc6d9507e4013305986bb9d0cc050de172faa2039623cb93177a0b7c5966933ad2ee6fa930dbfe24148b63561551364fdcc3a1e1a5381d62a9508c6bd86a43ed602e5fcc0cee2c8d2a67c7de50428fa72ef75fd4aafe4bbc17cb03ffeb69066e5c6ee65c1df67fc9c33515d45cfc504c2d2db213b36df5a6b7864ccf11061464048329f2a79b6935b4219aab811fa07896497ba8dc47c1f2e9207e4be7a4f3651bba673d4911787df8423cc60601785ac5072516954efa6e30f27c04136f6bdff2d23b0489b2d7c9aea7f5320d48c337eeb2dd4f06eedab55316ba8f45b6f9a584ae8241183a261b467be3b500febbb609a38895d92f0aa8ca31197e81c85aefcea4d7a5f0d4f7825de0260f9563db272720c723a38f935113d1f2a89b02303eced1312316f29001f224a730031ac6e002916a2077fff2de0cb740622692fde1ffe1811", +}, +// Pseudorandom 2, t=1 +{ + // K,B + "fcd9361d1dca1c7b9a24f754464eeda5727152bc98a818b2e720a0afa9103e10", + // T + 1, + // t + "d22ea954482f5bc511c6fcae80233d57", + // OUTPUT + "242f479249fefc782eb74cb5304e54cf9f1230ba8908c1a322650edd916ecf76527d3a84db32d8ca0931b0420c8bcf388042cb152ee080af416a37cf2e0406de5ebb9c27061650e72552ecadca5af451", +}, +// Pseudorandom 3, t=0 +{ + // K,B + "b445f9a92d267dbd3b2dd9ad0cf90538b4013b72df0a23ef997f7baf9440733a", + // T + 0, + // t + "1d16d4b08c19887a050603dc8f17bb6d", + // OUTPUT + "d609818f6c26b96efadb6e5d84ed63c4d426e133cc72acc222a161feb8810f99d0d8dbace6181b8f41e601cf7bd33a3a23e84bf8898505e222a42fb889fe759e48fda34e6d39c357e6445864e55633bc264d4f4d33d0afd20a51ad1b3d6d18288d6930ac9775e6928cdce46642b5b81bdbbdb469f1d6f1a889a2c76c0258ca6a95c5f590c54f1503ec46f1b3ad6e93233f9f4ca9a57bc14aa505f4678d9fee8fa7b8f047252569b83c79e3a4abea6d4a481e159e91dced13f58be46f41ef52f1ebb17cd68875f2dee11ab6409fe5f0d5a189fdc86b4b214f2ccd47d419e66ba3889bac4b7da810b3ba647082662c74c2e2972962d8af31fc05a22e0df7f5e87a6bdfb2b414bf55e46581ca982bca237a0af99030d079b6e81404b6bad3011bdf114e2d042e019342a41b06d1ece656ff994b80796747ca413f783c903f0980873c95b1b3d6d3c99410d75993a9b28ae23d26847da256e09f7c727f1b05eb1fa4aea6d0b4b69307363c2ec7d75e136c14f3ca44d2d2bf001095ee5505bcb56c06842233411e5bc38da56d97c1ce6b1807db9b832fc10625d55fb259a5cd75c0a1d27a8b8a8c9b2a98bdfe7903a927026f2d2616b481e13e3bf7eb1039ec892a2fa054fd8dd6aac76b0efbece35b374310583d1c5f594604c3a49b35af7c3065f9f5f3bbe5cac3e8522a0654463c", +}, +// Pseudorandom 3, t=1 +{ + // K,B + "b445f9a92d267dbd3b2dd9ad0cf90538b4013b72df0a23ef997f7baf9440733a", + // T + 1, + // t + "1d16d4b08c19887a050603dc8f17bb6d", + // OUTPUT + "85da4380c7376cdd451aef93c15303626a9a54b1b21ddf5fa88beb1ade9331438764e8ad4f640dae16e3708806bab62d948e2ac6210b198184d0bface602a49f606d13e72574d7cda3e8458736d180b6", +}, +}; + +static const struct uiv_testvec { + bool encrypt; + const char *keys; + const char *tweaks; + const char *x_l; + const char *x_r; + struct { + const char *y_l; + const char *y_r; + } y; +} UIV_TESTVECS[] = { +// All zeros, encrypt +{ + // Encrypt + True, + // {J,S} + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // H + "0000000000000000000000000000000000", + // X_L + "00000000000000000000000000000000", + // X_R + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // Output={Y_L, Y_R} + {"66e94bd4ef8a2c3b884cfa59ca342b2e", "66e94bd4ef8a2c3b884cfa59ca342b2e58e2fccefa7e3061367f1d57a4e7455a0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40deb3fa6794f8fd8f55a88dcbda9d68f2137cc9c83420077e7cf28ab2696b0df05d11452b58ac50aa2eb3a195b61b87e5c65a6dd5d7f7a84065d5a17ff46273086002496db63fa4b91bee387fa3030c95a73f8d0437e0915fbce5d7a62d8dab0a58b2431bc0bede02550f40238969ec780410befccde6944b69dd007debe39a9dbc5e24f519a4bdf478b1d9ec0b67125f28b06efaa55d79412ad628d45089c3c304f94db3a21df6cdaf6d2e2e3b355441eff64ad90527e752a4b2ebb4d0a1070ce2e2982e272fdb7cf4b584b095a0f957fdb828689437e37dc48b2ad379c6f3c6e957ee77afb88c65949ba12eec45c22865e4907ae42aee813898acdf91e2e4c21d828e0a76de2bb6bb6f869e5eef1f618dedd27562812b9a14e8996a5c352df3817e60d6ec20119a52c80a61ec195622627240212decca515feab63e2734587948a836a7de205cfec0c288351c"}, +}, +// All zeros, decrypt +{ + // Encrypt + False, + // {J,S} + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // H + "0000000000000000000000000000000000", + // X_L + "00000000000000000000000000000000", + // X_R + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // Output={Y_L, Y_R} + {"140f0f1011b5223d79587717ffd9ec3a", "66e94bd4ef8a2c3b884cfa59ca342b2e58e2fccefa7e3061367f1d57a4e7455a0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40deb3fa6794f8fd8f55a88dcbda9d68f2137cc9c83420077e7cf28ab2696b0df05d11452b58ac50aa2eb3a195b61b87e5c65a6dd5d7f7a84065d5a17ff46273086002496db63fa4b91bee387fa3030c95a73f8d0437e0915fbce5d7a62d8dab0a58b2431bc0bede02550f40238969ec780410befccde6944b69dd007debe39a9dbc5e24f519a4bdf478b1d9ec0b67125f28b06efaa55d79412ad628d45089c3c304f94db3a21df6cdaf6d2e2e3b355441eff64ad90527e752a4b2ebb4d0a1070ce2e2982e272fdb7cf4b584b095a0f957fdb828689437e37dc48b2ad379c6f3c6e957ee77afb88c65949ba12eec45c22865e4907ae42aee813898acdf91e2e4c21d828e0a76de2bb6bb6f869e5eef1f618dedd27562812b9a14e8996a5c352df3817e60d6ec20119a52c80a61ec195622627240212decca515feab63e2734587948a836a7de205cfec0c288351c"}, +}, +// All ones, encrypt +{ + // Encrypt + True, + // {J,S} + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + // H + "ffffffffffffffffffffffffffffffffff", + // X_L + "ffffffffffffffffffffffffffffffff", + // X_R + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + // Output={Y_L, Y_R} + {"7209baed4b605b158b7eb25de2200e83", "5546c0d2d8da37d92908803d88ff5a646e24a9f9c8c0e9f239726ccc5107d45ed813697aab0b27969930489e47c87475d71b92fc875e268d2ed92fa735b8258c657ff883512adf916a7a8819596e878415da7dc689fc658b862235133b4366e5bea11ece0990a544cb324e27313d67567797213ddb9102e75caca82a15035e44a306c906f8c17e2c88975808b35ad13443849d9ebec10f2c888738ff5b7cb3043b2bbd6098b167746addcc55238fb32d9ef404f3d0f7db0bc5f30aca0cf9ce5f87c989268d18b1069b33bbd5b7818a99603ec0d82871e75cffd1d84e2be1e0f8e8b3678b1ccd7a5a676d83fe0e68f09027ad912d58d2257932750b383e2f2fa3c889ee9d71919cc05d982230c6ff8b7e5e3ed302ed82bed429794c261aa009d231bb6c8675e513313432017cea50843a0309153f7f9d556330f19c38bc5ae6d33d63abaa7ebabd3335c1bf59a2121378288da679259bb1b8a8b027938f3e902c655c781e7f5d9514e53502e7ebc31e344344c3ae2a6397a9a8b846dab8a84174e91664804c7804bab09d6d40aeeb491d6f6184830ac7b5807418a05a7ab9938c3fdc18066b5d503f8c98e83be033b6fba905324267618cc6989b486e0decf7cc897d17be093286a4d4fb5016c3e3323ccc416a30473081473bd471e430194ec4e2ac0af3bca0577b78f4c70e4d"}, +}, +// All ones, decrypt +{ + // Encrypt + False, + // {J,S} + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + // H + "ffffffffffffffffffffffffffffffffff", + // X_L + "ffffffffffffffffffffffffffffffff", + // X_R + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + // Output={Y_L, Y_R} + {"a9166add184e00b007217cb4e4f52ee5", "c516fd6ce5172c45f85d10240fbeeada3699ca9b9c98cbbc9b92c12c1a459759e332751f270727b5235a3ffdc0fd102ef338438360402e9640b8586d4445f82936cc7efe2f3d71b89166adfbec5c83c36fba6f6572c8393458061ccdab00f4d15ee33292f59112fd744c53334c701f5af15d35ae23ca23edabe0a31ff9eecc9106992656fd859cbd3f6a6f2fa977f186402e5d8e5007deeeb9b61cc594b27c41f77c4c52b4cea539488fe838b757448e567e9870063935f79af81049177affbc898415f929911a164d78fef8b8beaffbbb775d2ff42e2aeab1f0e5153a50f48cfb6ffb078e8455ec3e51ff770d202071f759ed55ee57449b54d5b2d6d698afb5934bae5a9d8a48a93d2809a5548d79e8eab96c584ce2fb77fd4f319ca8ab688047ae44de222326a9b86a1ceadc033ca3303f9946abdaf74b2559a4b36f7c4ed5a32f7083ba6f9adc2a28ece0d866a66ffb8c58a91b7545456c04bd99cbfe27b4106c3930291fd03e886858ffb98e2de2c43ca34d165cbb25f5e93cff0c368849376d1f3d56ae879d413b85ae02b63a5b2b99df15a2065faa1763d2ab54004ff8fb3ede6e8abcc43e97c26c38a0028013339faf6d4e683a55a5566a45f3f1cc78f4f0aec5a1102629b03917679d8f635678920793e76e7e18f1b112d27895edb7f49b505001ab45b5370dcfbc27"}, +}, +// Pseudorandom 1, Encrypt +{ + // Encrypt + True, + // {J,S} + "22169d562646db8ce3322daf9fa8e84bed57dac18beabdb619b40f5a02786e439e6132a5b7e7445ef962e2c7f30a0b2ec994ee1935e1787d6f89cbc15b9254d5", + // H + "81b1a82c63d8dd9f682f734e82e259a14b", + // X_L + "db4adc246c6a54fe55e11901f08f0eee", + // X_R + "dccb8aa0570982d5b08fa6b4fbb3bc7bcd7e1cb374f114fcdd0ed53255c523c1e8ecabfbaab00105af9933eff304a40877e3006be82417e44462fc6955777baf2f2f9c99966ddee30b7c65050dcc8f5d7bc22f9192e1c4a83ca0a2338deca9da4fed14058812ace259e9851f50c83d97515b647ff56749a3c615e1860a404e9b05619a48aa3e5f09779e72c77dfdd1ab5d796860178938efffb4e43bda443c2fba0d5be14baa375d881ee5e14d760a12c4d9807c8c54b714a75324c4074296ba8c86beceb4dc2337946f0af67c759d999d56aceebefd80438dc625b0b50f749440e8cd5bcee1afa05ff8cff1bfd3e0e68930b74b3baa7e6cb723896afc3098326716e0554319c9f8f3683a8fd359ae48a3591dac67adeea6e24600037cb1a42c38b23a9e7c31e6d0b13b84e88341458050856c476f6875dfe17806e0cd72baeebd0e1108fb13088a887153a1d13bac414ed120c26bda5bc08202fc1489746305dcda5dfc3e6a869b52d63654f3bc35841a2345df8691caf1de06d5ebd214af729e239efd62d05060eab13fb973ffb41f461224e2eee1f739529d37e8db40c065e52de7b8f19fbf695470341062c7f212d8cf5310cc17f487e04e8ed03fe50f3758eda9e41bf37af62f94709b16e01b4305d1a5ccad2bcacc7e35d4a1d1a40c26dbf3153739175ca65ab59cc1c9", + // Output={Y_L, Y_R} + {"9ff8aec547f02caae7555ad7b0cb1372", "d2ceaad0ef52ac304d9550f0c365fa7728dca633f4f62228b241e47754dfa01c709e66f54a018e667573dbf5063c10a6167592250a8f6af17c68d5e190c5e8bdb40082b54e428ada58b3a805cdd56d87cc56591f8ac5f310eb37ce4d8a6ea6a80c3d7316f872aeb8a1a40ef7d1f0bbd1711d38c500eccc0acb88c1a3491ceee45bf82ba3fdf939dcbedb4f140fae21339f671df748d18e8bc8d72eb8e7cf18feafcd6f363345e2b05bc2d4d6f3affb8589d002aadb711d5ad2fa81398137b9e88f5a8663787e746bb878c0973d9b80145f8dd18bce30ea10e13ad07aeb469f62c4507ff8aaba09ed988a794232b5fc4e64466103366ed474fb99406fc80dd5ae5cb90001b1485476978dada0df83456feb3674ec7070b177871203410c5f7adbefbf5069c64bce59ef381514cb2a8d0804d855cca0a9c84d4c60c44e7242ffc479aabf357016166e9b184311c0e04dd9d1c512ae508b8f8c6bfdba68d46e338250f23668aaf11f45f57bfbc8e32d14ccab853af085a17405058ecd993cb21b41f8456c54a3900a50c270fc2b0931394ba257fd49bf79ae54d9c39a8504067b9cee1e42b688dcc606bee57006bc561b991dd10c56c129d1db8997e0d163fd06fca83249f146e348a4f35d0cb47d0ea6b3c6c587487f3816e13c2494d6d1e866fa182855cd668462a30b4e7019d2"}, +}, +// Pseudorandom 1, Decrypt +{ + // Encrypt + False, + // {J,S} + "22169d562646db8ce3322daf9fa8e84bed57dac18beabdb619b40f5a02786e439e6132a5b7e7445ef962e2c7f30a0b2ec994ee1935e1787d6f89cbc15b9254d5", + // H + "81b1a82c63d8dd9f682f734e82e259a14b", + // X_L + "db4adc246c6a54fe55e11901f08f0eee", + // X_R + "dccb8aa0570982d5b08fa6b4fbb3bc7bcd7e1cb374f114fcdd0ed53255c523c1e8ecabfbaab00105af9933eff304a40877e3006be82417e44462fc6955777baf2f2f9c99966ddee30b7c65050dcc8f5d7bc22f9192e1c4a83ca0a2338deca9da4fed14058812ace259e9851f50c83d97515b647ff56749a3c615e1860a404e9b05619a48aa3e5f09779e72c77dfdd1ab5d796860178938efffb4e43bda443c2fba0d5be14baa375d881ee5e14d760a12c4d9807c8c54b714a75324c4074296ba8c86beceb4dc2337946f0af67c759d999d56aceebefd80438dc625b0b50f749440e8cd5bcee1afa05ff8cff1bfd3e0e68930b74b3baa7e6cb723896afc3098326716e0554319c9f8f3683a8fd359ae48a3591dac67adeea6e24600037cb1a42c38b23a9e7c31e6d0b13b84e88341458050856c476f6875dfe17806e0cd72baeebd0e1108fb13088a887153a1d13bac414ed120c26bda5bc08202fc1489746305dcda5dfc3e6a869b52d63654f3bc35841a2345df8691caf1de06d5ebd214af729e239efd62d05060eab13fb973ffb41f461224e2eee1f739529d37e8db40c065e52de7b8f19fbf695470341062c7f212d8cf5310cc17f487e04e8ed03fe50f3758eda9e41bf37af62f94709b16e01b4305d1a5ccad2bcacc7e35d4a1d1a40c26dbf3153739175ca65ab59cc1c9", + // Output={Y_L, Y_R} + {"1c1593f30a020d44b7b2cf9b75204808", "c8135c678f97432394c2fa38ee6f590104a99028da2624a44d9a503adf1fe0d236ed5253d2e1cfca479c1b41609ef7cab58d7bb4d8e50e21108f837791f2e3066d3c40672f8e0f1a304d25ba20401a8aac6b15c1582788fe8996277b5cb554cd82e0920f212293b8bc4357349465f75e2f688a084d4c4741e2b384523d51cf94062cb7e6c1481eb48f1eb37e00937e0a2b2e12c88ac1b8ca2eef537b74b9f22e016b1a72818eddd1bde1e3643f4aa8fbf1e69543475131c17e8562c6c7d9a4375936fcc1c6ffeb131195e2168cd26368c3ab40f436563b4a5b6db2a7fa61e521321dad4d1aaaca8d0b38d68de26f402233d3bc25c78cd9019d2985f0f02c51cd07423726bd7ef3d19a8bb7b5a94d54ed86c460e7b02388fcedaa99902bc43c8339a171e89dc8123a9cd05287f2c0a39fdf24dd56dcf4326c163d38c9282d1f2f9a0faf50beb6e5caeb300a6192f6c1aaa5ba515bb677bb399edfcb05eab48870e79018d60ccdf3f1b5b6eb1e1a9e24a8a11da26c0919e6ec7db6a1260d6299e7a2830d48d3bf33b40f4c5cc0c4acae037a4bf5731fff732f44752bd002c8493f1d48ea6c5f0cbbd596d679c7130d687211e74a96473275f2c8df1634ad36aab16eb0221777e98f62057d669b51bee20ab45db78b619aa619a40245d9ddd074a35c54b77f7ccc0410c00719e423"}, +}, +// Pseudorandom 2, Encrypt +{ + // Encrypt + True, + // {J,S} + "e61126a280c66e99171b1ec940a75ba6d4c3301062760a9ff9f9b332433b8408af4a49ad5326b95da7f501bb8b34bce8ce6e8c33f57263a4779a161d3736b7e4", + // H + "837d18ad2b0162977d3461349b00bcfdd7", + // X_L + "4b9fa9b1d31ada9a15d29cd0bd920a53", + // X_R + "c819e68a3dbdb6e730e4c9ed6dc11187f7ef0f021f63f0da32b55c8e2c78d4bc55d0e487329542e0b63a8f57313a146443cb5b8ba9eaf77d7e80884333b0e33b806da9cb32e231b5a23aa9ffa6f598df337126b26d6f9ef0d6c6a1bb59d83d253ea0ddc7272d633eb785dd7649fb7618a3b2c721cfba7d3e3d4a95fafcb90c2c60a52258ff3da3e1ab1205747e049e4730d734eaa5744a18fa8b8c4aed37d28857a5877839a40659e9754795859dad3163d6358234072ae62f64e58c861fd2225c60a708bb9b199e2070315e6d8eda8365b7cdaf5d067280086fda2a304ccbf3177fb0d34bbc3b02b4aaf42e535fbf2a15b782a8f3004eecda69aade92eb7bc92b6d552172bd26db28dcdf36547fa2794bf598db51ba0578f176e0cd3db04bf8333819a17f9c0d6faa9128930a3d8e93170d1bdf4e17a26f794631c870d9fd0edc73c3ce51753cbf59f3c942b689ccd08d8c0e0b19840b5113b760893b7d3b3a7c8f2c8794cab2f35a49d1d3f8c93bc353f376904d1961d3958cdc7a1841fe305c5c48b98f3b829ab1540876c3bd9d73e979107ab6f8146fe8acf33bde92b0a0ec2088dca60ae8374bda9d36977e5653762e8744d2b66d5bcc26dde754ec5eb3f665fbdd1ce2d0a7a48c499c0a5b846a7cb3c478484703c31ebb0c20c66bc1c1722529be0bb850d9bff7437ca7", + // Output={Y_L, Y_R} + {"6db7f5e28e54c81ce9a22df58eef5f65", "bc742015a226d2f1f855c06e9c12ce9866a311622befc8ff5f796c1813308fecb8c91b7fdc00de93198498afeec55422f678fd1822131877c947236c4c978b0f0fc3d0ddeee5770bac3c635895d9b922399a0062e4c80b9ea753f89608ed6920fc2f8a9e09ba87b40c6ef2a9354524e7f0ac1d967ef520a348e37fccc35f584ed5270b7e4694cd263a25f8869e07693df3f9a5fbc6aa4f8697456fa830e07f6ab89d3ae18790b6208c09ec2cf530239bb7d514691a01b4a772233693dc398bc6b4a08e412dce4d3b3556c0aa8ad2d0ee474ef56c1dd232b677c2d38be103921b8373e9e1c8ef2e98ededce0439351e74ca751db03e8213cd6adb6ee5a7b3103675776b82e59120d21e4b4e03e01aa420c254530ed74c24dcc514ddb241450642dedd0c5b1a0f7c2a7af243b96f1d1312ff8448a0c3a2b9cdaa90c45d11fdd82e6b17bc83f246313d7d67dd380165ceac938f5cd7896ffb8c22669526345f42892e1cb2b5af64f39139e6f3d5ed8e03efa61d653bbfcdf387c9ccf9de686b9603a681143ccd21a12004c810acc7e9c17bbdeba632bc9e5f0c6d3cbf72c8e7b958fb66d38bdb77c1e170de541b0750d942e9f8bcf123bd4a369af220135816b6d9b09778a8bc5e0378ec82678c1344a978fd1b271376ac31ba3981a1639a3808a8cd35424daa91d59f6e34967434"}, +}, +// Pseudorandom 2, Decrypt +{ + // Encrypt + False, + // {J,S} + "e61126a280c66e99171b1ec940a75ba6d4c3301062760a9ff9f9b332433b8408af4a49ad5326b95da7f501bb8b34bce8ce6e8c33f57263a4779a161d3736b7e4", + // H + "837d18ad2b0162977d3461349b00bcfdd7", + // X_L + "4b9fa9b1d31ada9a15d29cd0bd920a53", + // X_R + "c819e68a3dbdb6e730e4c9ed6dc11187f7ef0f021f63f0da32b55c8e2c78d4bc55d0e487329542e0b63a8f57313a146443cb5b8ba9eaf77d7e80884333b0e33b806da9cb32e231b5a23aa9ffa6f598df337126b26d6f9ef0d6c6a1bb59d83d253ea0ddc7272d633eb785dd7649fb7618a3b2c721cfba7d3e3d4a95fafcb90c2c60a52258ff3da3e1ab1205747e049e4730d734eaa5744a18fa8b8c4aed37d28857a5877839a40659e9754795859dad3163d6358234072ae62f64e58c861fd2225c60a708bb9b199e2070315e6d8eda8365b7cdaf5d067280086fda2a304ccbf3177fb0d34bbc3b02b4aaf42e535fbf2a15b782a8f3004eecda69aade92eb7bc92b6d552172bd26db28dcdf36547fa2794bf598db51ba0578f176e0cd3db04bf8333819a17f9c0d6faa9128930a3d8e93170d1bdf4e17a26f794631c870d9fd0edc73c3ce51753cbf59f3c942b689ccd08d8c0e0b19840b5113b760893b7d3b3a7c8f2c8794cab2f35a49d1d3f8c93bc353f376904d1961d3958cdc7a1841fe305c5c48b98f3b829ab1540876c3bd9d73e979107ab6f8146fe8acf33bde92b0a0ec2088dca60ae8374bda9d36977e5653762e8744d2b66d5bcc26dde754ec5eb3f665fbdd1ce2d0a7a48c499c0a5b846a7cb3c478484703c31ebb0c20c66bc1c1722529be0bb850d9bff7437ca7", + // Output={Y_L, Y_R} + {"e6d9d943df0c57ffcf625bd142f023cc", "16fcd880981c22d459e61a502213668f6f040c57f9db8cf39fc07bce35a9df2e2cd083359e833944bb1da2d107caa11d171abfe5878787ca89c5460753a8df4c3af7d9e1091a68e1976eba0ba81005f60f1fb2f26b6163896070efb1c39e31d24bfcd23e897062645b5d5766ab81eef662ca789d4e5bf7aa76414d01acd67e9ec372e63f5a676fb4645cbff0c47b3ec0c667b781ac42a0fedb75eaf39fce4da7f37a660db56ca92836609ca32faa4987f232e89177cee0b45ab8d34ca1c9a9f29fcd057cc6e491387f75e01ffc40ddef01c0bb557803cb514afb19718a9b918ed266f5c3283d93b6fdd1232758f059a0f6f78b7d5e8cb0d61a7e974936b6bf007a0121db05051a3f3279c3b295de61af596f8ce8820480f666f963ad4c9af0490272f88eb01bdad77ca43c8d5cc3abf7b1d1b6b15890b43008d68ddbc9f2426985d6ef946cae5099b1b81eb500959d8e5571b438f796aafadfa85ae29e6373878f0eac3f91e75cd37c609064e57fc588bdba25f5f2cd095e14d01fe72ddb30f784fe97ccb7619ebe809a5acb24f73a69f9a3b348b99ff554fa316b4b16cb7cdcd79602ac17003057e7bff980521e43a57a43df4c13ed71740767ab277e1da09b371843aa1160b599b5cc0b1cb4c31d348718b64b9a6d66cd691185465ae5dcea649391b342bea21d430df41080"}, +}, +}; + +static const struct uiv_update_testvec { + const char *keys; + const char *nonce; + struct { + const char *new_keys; + const char *new_nonce; + } output; +} UIV_UPDATE_TESTVECS[] = { +// All zeros +{ + // {J,S} + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // N + "00000000000000000000000000000000", + // Output={{J',S'}, N'} + {"7941dd0a63d994703e63d94a446804213ab4fb1d2b7ba376590a2c241d1f508dc6a7f418a14503deb89b17aadb2806f73fc06e5d14e675f5ec880023d4f73296", "12dce4a0e5bc792b5b5a55f9c2f30e07"}, +}, +// All ones +{ + // {J,S} + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + // N + "ffffffffffffffffffffffffffffffff", + // Output={{J',S'}, N'} + {"be938fc23009440bfb5d7bba1d28428ec0897793bb878b8e1eb3ec1257b88024d551d770b56c9312de3dd4ac64e194c91185a89f2ba01f90b03b3acb93f634df", "4b263f03af0acda2f9721d0f4c0783c7"}, +}, +// Pseudorandom 1 +{ + // {J,S} + "bf9b13b7097f5eee96b15423348ebf7aa13da31a2955a72ff17c7f75f9fd92f3280bb2d8992bc2a5f70f8e4e10f0404f16f3a0bbb91975bae7e11180adcba6da", + // N + "1ecb6e1ee6f0531c233676fd1c3ca701", + // Output={{J',S'}, N'} + {"4c03bdb301aaa20b907ac88ecd3174bb1b476a00a81ad67cb4eceba22354ce8f241ab2da59d565781634e9252358006b5b78166ea59028e1ff40a71687dd2f11", "30151c332e40594324ef033a469d4f50"}, +}, +// Pseudorandom 2 +{ + // {J,S} + "e773e6211d22f03e0220bd6e69803b2d0bfbd6321a9e0184e49660bc1989318a868d5ccd3f769537c4990df2998cddc14cd853d8614c6e7e3548af9c824b457d", + // N + "d8097e67afff2d56a6279229cfb37f29", + // Output={{J',S'}, N'} + {"c9f14480f4d46a1e40ba3daaab9004ec0e7afab84f3c60da9f7f01ab46aab7a81e2138eed6f141047bc4169013450134586120852ca9a952417b402834fbedf4", "c79fdf8d9ae28e55eaed6e556e12b994"}, +}, +// Pseudorandom 3 +{ + // {J,S} + "a150329bf382e5c3b11619ac72ac3b2cdf55b19e94fd2f92bfca40ef540274ba571c53695d5d8f0d4d4935d2b599ee095754d3bbdd9929d60997eb4f745e0a48", + // N + "071652e3ea1b1d299ac07ab3df431090", + // Output={{J',S'}, N'} + {"7c7a284801c7aa0f727f8e24b87a2dca1b7550577924490291a7343924dfd1b9e2b86e4f7db39b77715888f7d3b9aa4ea44bd72a8b1eb79df0d46f25c130fc87", "3c8ecadfbe9ee9587332a6568c7f2476"}, +}, +}; + +typedef struct cgo_tv_state_t { + const char *keys; + const char *nonce; + const char *tprime; +} cgo_tv_state_t; + +static const struct cgo_relay_testvec { + bool inbound; + cgo_tv_state_t state_in; + const char *cmd; + const char *tag; + const char *msg; + struct { + cgo_tv_state_t state; + struct { + const char *t_out; + const char *msg_out; + } result; + } output; +} CGO_RELAY_TESTVECS[] = { +// All zeros, inbound +{ + // Inbound + True, + // R = {K, N, T'} + {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000"}, + // AD + "00", + // T + "00000000000000000000000000000000", + // C + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // Output={R', {T_out, C_out}} + {{"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", "66e94bd4ef8a2c3b884cfa59ca342b2e"}, {"66e94bd4ef8a2c3b884cfa59ca342b2e", "66e94bd4ef8a2c3b884cfa59ca342b2e58e2fccefa7e3061367f1d57a4e7455a0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40deb3fa6794f8fd8f55a88dcbda9d68f2137cc9c83420077e7cf28ab2696b0df05d11452b58ac50aa2eb3a195b61b87e5c65a6dd5d7f7a84065d5a17ff46273086002496db63fa4b91bee387fa3030c95a73f8d0437e0915fbce5d7a62d8dab0a58b2431bc0bede02550f40238969ec780410befccde6944b69dd007debe39a9dbc5e24f519a4bdf478b1d9ec0b67125f28b06efaa55d79412ad628d45089c3c304f94db3a21df6cdaf6d2e2e3b355441eff64ad90527e752a4b2ebb4d0a1070ce2e2982e272fdb7cf4b584b095a0f957fdb828689437e37dc48b2ad379c6f3c6e957ee77afb88c65949ba12eec45c22865e4907ae42aee813898acdf91e2e4c21d828e0a76de2bb6bb6f869e5eef1f618dedd27562812b9a14e8996a5c352df3817e60d6ec20119a52c80a61ec195622627240212decca515feab63e2734587948a836a7de205cfec0c288351c"}}, +}, +// All zeros, outbound +{ + // Inbound + False, + // R = {K, N, T'} + {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000"}, + // AD + "00", + // T + "00000000000000000000000000000000", + // C + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // Output={R', {T_out, C_out}} + {{"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", "66e94bd4ef8a2c3b884cfa59ca342b2e"}, {"66e94bd4ef8a2c3b884cfa59ca342b2e", "66e94bd4ef8a2c3b884cfa59ca342b2e58e2fccefa7e3061367f1d57a4e7455a0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40deb3fa6794f8fd8f55a88dcbda9d68f2137cc9c83420077e7cf28ab2696b0df05d11452b58ac50aa2eb3a195b61b87e5c65a6dd5d7f7a84065d5a17ff46273086002496db63fa4b91bee387fa3030c95a73f8d0437e0915fbce5d7a62d8dab0a58b2431bc0bede02550f40238969ec780410befccde6944b69dd007debe39a9dbc5e24f519a4bdf478b1d9ec0b67125f28b06efaa55d79412ad628d45089c3c304f94db3a21df6cdaf6d2e2e3b355441eff64ad90527e752a4b2ebb4d0a1070ce2e2982e272fdb7cf4b584b095a0f957fdb828689437e37dc48b2ad379c6f3c6e957ee77afb88c65949ba12eec45c22865e4907ae42aee813898acdf91e2e4c21d828e0a76de2bb6bb6f869e5eef1f618dedd27562812b9a14e8996a5c352df3817e60d6ec20119a52c80a61ec195622627240212decca515feab63e2734587948a836a7de205cfec0c288351c"}}, +}, +// All ones, inbound +{ + // Inbound + True, + // R = {K, N, T'} + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff"}, + // AD + "ff", + // T + "ffffffffffffffffffffffffffffffff", + // C + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + // Output={R', {T_out, C_out}} + {{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff", "7209baed4b605b158b7eb25de2200e83"}, {"7209baed4b605b158b7eb25de2200e83", "5546c0d2d8da37d92908803d88ff5a646e24a9f9c8c0e9f239726ccc5107d45ed813697aab0b27969930489e47c87475d71b92fc875e268d2ed92fa735b8258c657ff883512adf916a7a8819596e878415da7dc689fc658b862235133b4366e5bea11ece0990a544cb324e27313d67567797213ddb9102e75caca82a15035e44a306c906f8c17e2c88975808b35ad13443849d9ebec10f2c888738ff5b7cb3043b2bbd6098b167746addcc55238fb32d9ef404f3d0f7db0bc5f30aca0cf9ce5f87c989268d18b1069b33bbd5b7818a99603ec0d82871e75cffd1d84e2be1e0f8e8b3678b1ccd7a5a676d83fe0e68f09027ad912d58d2257932750b383e2f2fa3c889ee9d71919cc05d982230c6ff8b7e5e3ed302ed82bed429794c261aa009d231bb6c8675e513313432017cea50843a0309153f7f9d556330f19c38bc5ae6d33d63abaa7ebabd3335c1bf59a2121378288da679259bb1b8a8b027938f3e902c655c781e7f5d9514e53502e7ebc31e344344c3ae2a6397a9a8b846dab8a84174e91664804c7804bab09d6d40aeeb491d6f6184830ac7b5807418a05a7ab9938c3fdc18066b5d503f8c98e83be033b6fba905324267618cc6989b486e0decf7cc897d17be093286a4d4fb5016c3e3323ccc416a30473081473bd471e430194ec4e2ac0af3bca0577b78f4c70e4d"}}, +}, +// All ones, outbound +{ + // Inbound + False, + // R = {K, N, T'} + {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff"}, + // AD + "ff", + // T + "ffffffffffffffffffffffffffffffff", + // C + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + // Output={R', {T_out, C_out}} + {{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff", "7209baed4b605b158b7eb25de2200e83"}, {"7209baed4b605b158b7eb25de2200e83", "5546c0d2d8da37d92908803d88ff5a646e24a9f9c8c0e9f239726ccc5107d45ed813697aab0b27969930489e47c87475d71b92fc875e268d2ed92fa735b8258c657ff883512adf916a7a8819596e878415da7dc689fc658b862235133b4366e5bea11ece0990a544cb324e27313d67567797213ddb9102e75caca82a15035e44a306c906f8c17e2c88975808b35ad13443849d9ebec10f2c888738ff5b7cb3043b2bbd6098b167746addcc55238fb32d9ef404f3d0f7db0bc5f30aca0cf9ce5f87c989268d18b1069b33bbd5b7818a99603ec0d82871e75cffd1d84e2be1e0f8e8b3678b1ccd7a5a676d83fe0e68f09027ad912d58d2257932750b383e2f2fa3c889ee9d71919cc05d982230c6ff8b7e5e3ed302ed82bed429794c261aa009d231bb6c8675e513313432017cea50843a0309153f7f9d556330f19c38bc5ae6d33d63abaa7ebabd3335c1bf59a2121378288da679259bb1b8a8b027938f3e902c655c781e7f5d9514e53502e7ebc31e344344c3ae2a6397a9a8b846dab8a84174e91664804c7804bab09d6d40aeeb491d6f6184830ac7b5807418a05a7ab9938c3fdc18066b5d503f8c98e83be033b6fba905324267618cc6989b486e0decf7cc897d17be093286a4d4fb5016c3e3323ccc416a30473081473bd471e430194ec4e2ac0af3bca0577b78f4c70e4d"}}, +}, +// Pseudorandom 1, inbound +{ + // Inbound + True, + // R = {K, N, T'} + {"3ab14ee71f417dc6cba5aaaba8eff9c3cd5f408020b4e8586ff734dad4aff593f4d863afbc519eba44d6e8643ae3fabf7ba8cd0803094d82b18acb03c1207927", "e616de4990c8efc5e58131f635f35776", "310495f73b4d20f4d8069bb1d2ed5638"}, + // AD + "88", + // T + "5de86524ea1542e8f1b8ea118c12d1fd", + // C + "43f965f6b01b939d972a2b9bd3b2cefe4315da3f97b51af875dc7717b97d9ac37c9e18e4a00fdcc65dde90ebd6c2909fa3e1d83cb07863596408f94334522c1e04688855c44dbee3bad7ab2872c1b87493766c6e0639bcdbbb2717be2d848c37ef034607f6b05facec43f5c1ef99a78631ab8387385cf0b272b0759513807451c63b4ba7f8908e5822b43bea59013c4bba59ab70dd9951ad1d015ccc9b4067aa02cc40d530e2e2bc473906f03a69f5f92183d2094af98edd23199940572edf095a42ec9be535982d6bdf8e525cf2a26011082d0ad019bd3580be817b1049db2e3ca35ee1212b15faa2c35bd4b342c930cc44e77336d84fcbd36454aa3a3cd7961047b58fd26383d1fbe0beb250f8389c1e949728d3d8218b36f4989e3499ced2e660b7ed6a5edb51a36f2fe9f32238f1a318141fcb3bed2c8a34efb5f98b8bccf2548fb542826e6abf3db576ccb064c905c246ecb4ecd5d638e7d3705b549df99de126227485f8dcb499dabc6f3e5d9735a70f1073f708293b2855dd64c981bdfceb8c75bd7d692f7a2d26f453c302d4593af2bb17a785d52bc87914f62056326dbedb8b5d45333dc7fca8d5eea986b1c19ff122b60c74f9220a3eaddf0f40ee105fee1c336c93afef1804a81bb57f918dbd7ef220428dd26c6d83c95e6adcec8f997b8ed810dcdc0bb3867f37", + // Output={R', {T_out, C_out}} + {{"3ab14ee71f417dc6cba5aaaba8eff9c3cd5f408020b4e8586ff734dad4aff593f4d863afbc519eba44d6e8643ae3fabf7ba8cd0803094d82b18acb03c1207927", "e616de4990c8efc5e58131f635f35776", "84fe1db6790ae6e32e418a70bb70d695"}, {"84fe1db6790ae6e32e418a70bb70d695", "be638eacedc6fbbdf8d9f75f414b3b43ff4fdef3c261a24ffec5eae75a3a1016432bdfc6df956b1e19eb011dc891238d86938ee98d7e0beac3df360818e45aff037e42e345153f5814937d53f92492b03f526c3e85464912742bbb26df3258e7fe0e3fdd7c8b855122543a6d277f896bec6875e6d320d5f329b90d1e57ea2aa9691542c13c9601f7dae18313737387a85eff1ba244be546cd1511782555b8ab90306bd85170e3a489c13f892f4430ae39c49ab1514d05b510709da34651dbe600f68642541ee9ab2163a0e442b6017014c80e05b622d53fa40cbd5eaafbfec34289c5b48c2908a2e7749e1c3f0cceab57bea1f3c925756e477d0c32c1d6262f259a5b20b8234aba22c36604fa6c9f0b953724089b549b7442adae8a91a7a7c3070aad0099d3cb94c17b2f767a8933bbae1de8322d73d9688f6f211b9b3922e758b2407179083490d3bd2d3f366e012f86aa268c2d24ea843953b3cc4a83f33c795f5df035da1c7ef4b160d013d201adcc469def9b4c6334cb9f091f789ba1a23cb2a667564eea9ea3a24c5f1fea54c8f7842ba6266c5405b6cf5f611ee4d0253b09500ce0e704ae2b9aad6271b59ac3e34a446c03c1cf261757c6798d6cc9fe6be8793666d8d046cb5aee99a0598184b3c614444a7b0ed812fe46c1e7ae9a0aee9f49908e705896edf53a3a90f"}}, +}, +// Pseudorandom 1, outbound +{ + // Inbound + False, + // R = {K, N, T'} + {"3ab14ee71f417dc6cba5aaaba8eff9c3cd5f408020b4e8586ff734dad4aff593f4d863afbc519eba44d6e8643ae3fabf7ba8cd0803094d82b18acb03c1207927", "e616de4990c8efc5e58131f635f35776", "310495f73b4d20f4d8069bb1d2ed5638"}, + // AD + "88", + // T + "5de86524ea1542e8f1b8ea118c12d1fd", + // C + "43f965f6b01b939d972a2b9bd3b2cefe4315da3f97b51af875dc7717b97d9ac37c9e18e4a00fdcc65dde90ebd6c2909fa3e1d83cb07863596408f94334522c1e04688855c44dbee3bad7ab2872c1b87493766c6e0639bcdbbb2717be2d848c37ef034607f6b05facec43f5c1ef99a78631ab8387385cf0b272b0759513807451c63b4ba7f8908e5822b43bea59013c4bba59ab70dd9951ad1d015ccc9b4067aa02cc40d530e2e2bc473906f03a69f5f92183d2094af98edd23199940572edf095a42ec9be535982d6bdf8e525cf2a26011082d0ad019bd3580be817b1049db2e3ca35ee1212b15faa2c35bd4b342c930cc44e77336d84fcbd36454aa3a3cd7961047b58fd26383d1fbe0beb250f8389c1e949728d3d8218b36f4989e3499ced2e660b7ed6a5edb51a36f2fe9f32238f1a318141fcb3bed2c8a34efb5f98b8bccf2548fb542826e6abf3db576ccb064c905c246ecb4ecd5d638e7d3705b549df99de126227485f8dcb499dabc6f3e5d9735a70f1073f708293b2855dd64c981bdfceb8c75bd7d692f7a2d26f453c302d4593af2bb17a785d52bc87914f62056326dbedb8b5d45333dc7fca8d5eea986b1c19ff122b60c74f9220a3eaddf0f40ee105fee1c336c93afef1804a81bb57f918dbd7ef220428dd26c6d83c95e6adcec8f997b8ed810dcdc0bb3867f37", + // Output={R', {T_out, C_out}} + {{"3ab14ee71f417dc6cba5aaaba8eff9c3cd5f408020b4e8586ff734dad4aff593f4d863afbc519eba44d6e8643ae3fabf7ba8cd0803094d82b18acb03c1207927", "e616de4990c8efc5e58131f635f35776", "84fe1db6790ae6e32e418a70bb70d695"}, {"84fe1db6790ae6e32e418a70bb70d695", "be638eacedc6fbbdf8d9f75f414b3b43ff4fdef3c261a24ffec5eae75a3a1016432bdfc6df956b1e19eb011dc891238d86938ee98d7e0beac3df360818e45aff037e42e345153f5814937d53f92492b03f526c3e85464912742bbb26df3258e7fe0e3fdd7c8b855122543a6d277f896bec6875e6d320d5f329b90d1e57ea2aa9691542c13c9601f7dae18313737387a85eff1ba244be546cd1511782555b8ab90306bd85170e3a489c13f892f4430ae39c49ab1514d05b510709da34651dbe600f68642541ee9ab2163a0e442b6017014c80e05b622d53fa40cbd5eaafbfec34289c5b48c2908a2e7749e1c3f0cceab57bea1f3c925756e477d0c32c1d6262f259a5b20b8234aba22c36604fa6c9f0b953724089b549b7442adae8a91a7a7c3070aad0099d3cb94c17b2f767a8933bbae1de8322d73d9688f6f211b9b3922e758b2407179083490d3bd2d3f366e012f86aa268c2d24ea843953b3cc4a83f33c795f5df035da1c7ef4b160d013d201adcc469def9b4c6334cb9f091f789ba1a23cb2a667564eea9ea3a24c5f1fea54c8f7842ba6266c5405b6cf5f611ee4d0253b09500ce0e704ae2b9aad6271b59ac3e34a446c03c1cf261757c6798d6cc9fe6be8793666d8d046cb5aee99a0598184b3c614444a7b0ed812fe46c1e7ae9a0aee9f49908e705896edf53a3a90f"}}, +}, +// Pseudorandom 2, inbound +{ + // Inbound + True, + // R = {K, N, T'} + {"302b0f1333b68c8c2c367b1aa02701e07f715b2fc28f34e124893657a98d5442339c9dc55adec43305e5c03e0b9ac69d35f31e92c6bf9aa066607895b453b89e", "02899ad22f2f01d8768323613476c78c", "db34fd587ddf145c5aa1ac58bef5756d"}, + // AD + "ab", + // T + "867464943ada7a8decef75a961214f9a", + // C + "0f0cfeed7dcd312b7b769cc859b20a8e18da16451925a0153ae6a57226fec6b2048dea4584e47e078ecbce0f2ca6413a2bb4e30fd6628a036d1749556adb012d110e23c979dc26c2aee3f24bf2ccf27cfd6d294073a20e9c4c5401c09bc4b2e38b6002b2b320b408b99798db1222034813fd70723a141de5a11679a56b704b1cd8751e919565ea129ce1f9fc2883c7d4cac0d8fd4da61d57501788105ef0d622fca6bfbf72b11a3a03d388c99e4aea582db920872be152bf89dc672383263936d93c0c9915db9b103cbcff5e90f4d9dbae0c4ea8e8464332b9ffaa478735faee477e28355be86f572e2ccca91e60e1874edd1d592b0f4f625276dd5a270a830147365c3fa20168088477c08c56352015ee962d1ce6d24456c96b649921ecffbafa21ff713e2d0da18f2e72e49830ada7878b7fba8eb3700c1db10cbd62ddd6bf1350374a10df5578e6b0774b510d15f11bbe95fd3ed87a8bd68c5110621e12d708f266ee8e48979e2d0fb222c008faea9d9f4ae14951301f9359ed133c5328e6fdd817e83ad84341500752b052bea6432841c801ffd68856c597dc0ce006c89222f1173194044de3d0f75b670923c4de63c683de97990af9430f83ba7510220f56a46e8a47b6ee46a4fcc132d33e059dc3783e3dfe2ecd673588feeb4af5945e18693238520aada42ab371ff4e", + // Output={R', {T_out, C_out}} + {{"302b0f1333b68c8c2c367b1aa02701e07f715b2fc28f34e124893657a98d5442339c9dc55adec43305e5c03e0b9ac69d35f31e92c6bf9aa066607895b453b89e", "02899ad22f2f01d8768323613476c78c", "61637a70ae9a95105b1e78ff6892e60e"}, {"61637a70ae9a95105b1e78ff6892e60e", "b9b2516c278a8b4bba221b185e990d4814e94b8ea6ef5e7585945ec250c1d427d2c322e3c3f3f406a43408296e0820debb518543be2ed9a18d61b0ac46e1de159101fb6431711f43eb3e35a0ab1451c30e4d895f888cfada66cffe67de67254e8bd4b3e0834f07033206c3449ae8f8ced104c14a0df0ac8fc2757ae63e1cdc99da87f5bc9fc66d2bb5216e641c04f234da501fa721263229948e51ce73c355e302219f6a8f24daeb6c771ff7aeb7f16fc431551618d32c3ea78543bc71d95593a1675b5a1fa936db5945dff819abb197da2dfa460a7619033c9de74679f02fa73badd4ce89a43b25517a12eedd5b3464ca44f4c68e8f14e671f366a541f340b376a5890202f72e15cc22ba1d2573190e3cc65ba042e874d05ed11a16bd5f93a8defb047a223d647b54b0531fc76beb3c7a23766d7cf84479aaa3c25a8b7cc40a31603283aaf98daedc2990c2c4b6006d0a9e80be6bc1a34e65b12a7414acc4046f5f653b0ea2b44e1c93ce1ae8763aa88c366349db4b2305b57030290e989f65d035fdf0375bd889552a79f6647a5810ed2020c1821e78b150501f3e41e4b836ea079fc7b89e215efd9dfb02bcbeb857b0940cb70f64840b40cddf0fc3e3ff3e561b709d8eccbd62b6cb28ebe49003cd1569eb569e87bc24c5d245079da7ae610146aef4225b6f3c6e0ce3aacc"}}, +}, +}; + +static const struct cgo_relay_originate_testvec { + cgo_tv_state_t state_in; + const char *cmd; + const char *msg; + struct { + cgo_tv_state_t state; + struct { + const char *t_out; + const char *msg_out; + } result; + } output; +} CGO_RELAY_ORIGINATE_TESTVECS[] = { +// All zeroes, originating +{ + // R = {K, N, T'} + {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000"}, + // AD + "00", + // M + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // Output={R', {T_out, C_out}} + {{"7941dd0a63d994703e63d94a446804213ab4fb1d2b7ba376590a2c241d1f508dc6a7f418a14503deb89b17aadb2806f73fc06e5d14e675f5ec880023d4f73296", "12dce4a0e5bc792b5b5a55f9c2f30e07", "66e94bd4ef8a2c3b884cfa59ca342b2e"}, {"66e94bd4ef8a2c3b884cfa59ca342b2e", "66e94bd4ef8a2c3b884cfa59ca342b2e58e2fccefa7e3061367f1d57a4e7455a0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40deb3fa6794f8fd8f55a88dcbda9d68f2137cc9c83420077e7cf28ab2696b0df05d11452b58ac50aa2eb3a195b61b87e5c65a6dd5d7f7a84065d5a17ff46273086002496db63fa4b91bee387fa3030c95a73f8d0437e0915fbce5d7a62d8dab0a58b2431bc0bede02550f40238969ec780410befccde6944b69dd007debe39a9dbc5e24f519a4bdf478b1d9ec0b67125f28b06efaa55d79412ad628d45089c3c304f94db3a21df6cdaf6d2e2e3b355441eff64ad90527e752a4b2ebb4d0a1070ce2e2982e272fdb7cf4b584b095a0f957fdb828689437e37dc48b2ad379c6f3c6e957ee77afb88c65949ba12eec45c22865e4907ae42aee813898acdf91e2e4c21d828e0a76de2bb6bb6f869e5eef1f618dedd27562812b9a14e8996a5c352df3817e60d6ec20119a52c80a61ec195622627240212decca515feab63e2734587948a836a7de205cfec0c288351c"}}, +}, +// Pseudorandom 1, originating +{ + // R = {K, N, T'} + {"3ab14ee71f417dc6cba5aaaba8eff9c3cd5f408020b4e8586ff734dad4aff593f4d863afbc519eba44d6e8643ae3fabf7ba8cd0803094d82b18acb03c1207927", "e616de4990c8efc5e58131f635f35776", "310495f73b4d20f4d8069bb1d2ed5638"}, + // AD + "88", + // M + "43f965f6b01b939d972a2b9bd3b2cefe4315da3f97b51af875dc7717b97d9ac37c9e18e4a00fdcc65dde90ebd6c2909fa3e1d83cb07863596408f94334522c1e04688855c44dbee3bad7ab2872c1b87493766c6e0639bcdbbb2717be2d848c37ef034607f6b05facec43f5c1ef99a78631ab8387385cf0b272b0759513807451c63b4ba7f8908e5822b43bea59013c4bba59ab70dd9951ad1d015ccc9b4067aa02cc40d530e2e2bc473906f03a69f5f92183d2094af98edd23199940572edf095a42ec9be535982d6bdf8e525cf2a26011082d0ad019bd3580be817b1049db2e3ca35ee1212b15faa2c35bd4b342c930cc44e77336d84fcbd36454aa3a3cd7961047b58fd26383d1fbe0beb250f8389c1e949728d3d8218b36f4989e3499ced2e660b7ed6a5edb51a36f2fe9f32238f1a318141fcb3bed2c8a34efb5f98b8bccf2548fb542826e6abf3db576ccb064c905c246ecb4ecd5d638e7d3705b549df99de126227485f8dcb499dabc6f3e5d9735a70f1073f708293b2855dd64c981bdfceb8c75bd7d692f7a2d26f453c302d4593af2bb17a785d52bc87914f62056326dbedb8b5d45333dc7fca8d5eea986b1c19ff122b60c74f9220a3eaddf0f40ee105fee1c336c93afef1804a81bb57f918dbd7ef220428dd26c6d83c95e6adcec8f997b8ed810dcdc0bb3867f37", + // Output={R', {T_out, C_out}} + {{"c24b000843784bc008c70b977e62ed82085ed0cda9f841da2c89d1832e763b9e283c36875fa41caae5913293d8014451c10fedddf362849bcaaa1833a3b8fcd8", "497798331f2c32ca4de4b1b55b82c306", "b8b3b69f6e175a5649013ca99c838291"}, {"b8b3b69f6e175a5649013ca99c838291", "94773462bcfb3728ec6f2f4e3b7020234abd8a6fa778a49788509b6452556e951f49a20a552035b38143907c59788c6865dac89ec22af08cc98ed1fcf55debccd3bb18c91340205524b36e1ec0ca0c082f79c575e7e0c77ade4b6084f6b6a12592f9a24c715bc92ee2531641cb11c6e9a462242354d655c392fccc1c84af5217cefb9806eb9990cf36034188600b2a123d860d0c661362f511e7d4eafc46a38c030fbe884a681fedef9c04375793435784579a3640ce2d75d9553936e877c3c24b33e0ffa88d59fed2fbbaf91e446c8d37a6b1400f7dfcd6ba8fa425c36e111a71c661f81ac8824524038a8dab5ac5a17014f4e7af5638e27e14869b51a9a2ff43fc9b3d7205e9f2e9f20c80d52778c26589179631345b0cedcb76d4862e3f88dcd27074da5d8b36ce7f2fbb972dafe327fd0e68620f5b284b1a7f1e64e33df2abd0f4aabe30b0e168f52ea39f1c5755276bc5c25cfa3960c2646ac13cbf2d9d1748e9c8db3664a98b4ef4e6f4a401cde973a62f0d4a6409447dfd2500b916015e50d79eeaa6508295d7959cb45af82b2b1b081b84911f9feeb994ddc5c472b342eef82d611809051658215158b99f5e3002e97f343e3b29eaad6489557573780b13956e4665dd0b859631d9937d4f90e0f810b36babfe8a1371b6eb985fd600d8353962cca9ce5b9d2ebf0da8"}}, +}, +// Pseudorandom 2, originating +{ + // R = {K, N, T'} + {"302b0f1333b68c8c2c367b1aa02701e07f715b2fc28f34e124893657a98d5442339c9dc55adec43305e5c03e0b9ac69d35f31e92c6bf9aa066607895b453b89e", "02899ad22f2f01d8768323613476c78c", "db34fd587ddf145c5aa1ac58bef5756d"}, + // AD + "ab", + // M + "0f0cfeed7dcd312b7b769cc859b20a8e18da16451925a0153ae6a57226fec6b2048dea4584e47e078ecbce0f2ca6413a2bb4e30fd6628a036d1749556adb012d110e23c979dc26c2aee3f24bf2ccf27cfd6d294073a20e9c4c5401c09bc4b2e38b6002b2b320b408b99798db1222034813fd70723a141de5a11679a56b704b1cd8751e919565ea129ce1f9fc2883c7d4cac0d8fd4da61d57501788105ef0d622fca6bfbf72b11a3a03d388c99e4aea582db920872be152bf89dc672383263936d93c0c9915db9b103cbcff5e90f4d9dbae0c4ea8e8464332b9ffaa478735faee477e28355be86f572e2ccca91e60e1874edd1d592b0f4f625276dd5a270a830147365c3fa20168088477c08c56352015ee962d1ce6d24456c96b649921ecffbafa21ff713e2d0da18f2e72e49830ada7878b7fba8eb3700c1db10cbd62ddd6bf1350374a10df5578e6b0774b510d15f11bbe95fd3ed87a8bd68c5110621e12d708f266ee8e48979e2d0fb222c008faea9d9f4ae14951301f9359ed133c5328e6fdd817e83ad84341500752b052bea6432841c801ffd68856c597dc0ce006c89222f1173194044de3d0f75b670923c4de63c683de97990af9430f83ba7510220f56a46e8a47b6ee46a4fcc132d33e059dc3783e3dfe2ecd673588feeb4af5945e18693238520aada42ab371ff4e", + // Output={R', {T_out, C_out}} + {{"60b9d644a620c3f36181f6f3ecbb0be41d400b78822dd3247247d286a5b80baec2dfc3694f119beab9b40fd538844d159e7bf256fb2ce53fe33e4c8763180b0a", "094b5cdc3a49cc51aab3e1f331f03df6", "99daac5f8bdba8f4807e719c768cb3ce"}, {"99daac5f8bdba8f4807e719c768cb3ce", "30db410a04452437045b7f51210bd01eab5d034c146c766ef73a9500b1c7f75d5ea7b1fe47f8eb927bcac6fb756e80cdd48b381a431c858432047410cd526bd91283a53ab94371bff4c4370e8dc8671349316759bdd01bbe432423a66a8497a7091c8056af277112a04c65946dbf82d076e66647456e991ff44c689e57d475956a3c1dd5f1a870e711ed57dc287b96f6437e2e4194e341a2dc5913631eab53f899f09ee41361b4d74c508f42ae972c93d21797342242b7e4e39d24888dfd215458a8e134fb9da152a0b1e5304685919f5dc3da8a0dc04906763075432ce92afe1283b1d344c36832bb54cf47a28c13263fd34558ef1c7827b4d8c1aea20f23316b04d1750bf42b6317a421618c3af00f5469d28aa52e8aef1e76d80754a52982285c1d558c61268d40f2e931c0b3848f70da72b07867df56de689a19f2db0a379207ca462a0bc97a3ea7d111a144454432e4d0eb3ee1fc5f905923effa1b196ce29f9c07d32fabcdfcce4c2d582a7b80b65fff05ffd2b5e7d91fca0817e9458c68d6919ad442ca1d20d77c7c0b6e924af2665d9eeaeeac28692f978eecd4e1d5878ce300f8035d0a7ff6050a172c1d328bb392e4d55198a976d45f7d9670eeb67ed4b79c95b219fc9cf3c7613c128e2224d2799d9459b4941a248589d7bc1cd644ac96aa49e0d630288b73a028"}}, +}, +// Pseudorandom 3, originating +{ + // R = {K, N, T'} + {"f69da975bf0055353e52a8b3fa834b1bcedf1445e4b2f1dca13f59a306e8040ce64d5922b2b9de5735a96e2fa2e9524e99ce5b8888fd000f570f148191bdb54f", "8e4219f5b72d0bbf1f47005632816b36", "c5301aaf38e66f698293618354d06e0a"}, + // AD + "90", + // M + "727ee8dff3a22ad873545c040d22a67a6caac97c308a0f4109da1a1d67695d9fd7570a27593fefcdc0ce568ff6f8998a03791e12720a86d95110540073e104a86ba14ac9e58705ff20ebfced49a91d832a635924193dbf14ff995da7d4cbb4752d364908c1096606cee429adad73513bfd848fb6132fad9531178b419d4c6670224e858ff0a413b083b58cb6a8297bc7474e48050ac926c3a568df88feb135e9011d26eb2327c0797fd821a9bca3052e116f26844a2a5d23542ea666f2225700dd134cc166e2cd36f88be6a4b367be083e7d7be99a9205489de7ece3308846fcad66dd249ada0c559999fc3dd9e36036831e3e2aa51d0190b227f3bb54b365ea668009298612308361537b66e143fdb5b3da43a6a141910b7daef3dd4c5a819749c1d5d005c3c39bf7d2d749754614e794c51a965694904d30fa5be6fba2360ccf46c4ed2b4829f6434bb8951e82580a4da3d7075d734c4c12560693b9bacb1ce7ee953d7ce9dec24d7a129e8e582a3e2e1168e7b966c2e435b21f9b7ba83e27023b287e7fc420c5934af909e1a3fcb8415347c5ebd30aebaf6fe11cbea60d8dbe78cd54736dcb6a0cab929175417510d0ab2c4688b91c8d75d5a9b51ff15fddeb1a08402dc7748eb5b9d219f4ecb4116be1765a03fd06fc01d8e366b945cf6557257ef0ec2b74619d4e081c89", + // Output={R', {T_out, C_out}} + {{"c658a50d452e0ac66a543a15dfb30f791509266d47e259d56374787e3e2ccc49a06c6d2d65553223ace6097a3fb7cee5f4af4602a4c73c8128391e2454b7caa1", "2436c77f19dee78ff65f39967659e7d5", "276d823e18b1a06c0fe224431630b7b2"}, {"276d823e18b1a06c0fe224431630b7b2", "545b61a9a2d88a6f0e389c864fcdec76f5d04b836a1d1a48b26895f4c8829af6de70ac08578f2e1cd054f4a9ab5efbdbd872b712ca451270f472a621a95827a382829d794395ae507ccc1df35a677d069207296faa9c2a1d3a454ada30deac8e3a2fd4cfa69c298f9ae0f6a6d15b2a3404c84233c29fc8e85cdf009dfab83ff18f0a7f9ed8a4d7ef10e6fae321c5c526f01dc5f045ec9504e270cb634b072b03d1a0ef8b013913684b935d2883bdfd49ce8dbde8e603663b7ebe869072d61462aea8f7da0d7bc4be054032995c5f5862493f3e45580d9415a3f68eb083092a4c1066f06725da1751b025efb015683cc1935cfafafe7aef90d9c18f2a5f2cce060716838303ca8b7de3164fc09a9d15ccbedd7c24bd47f9585b3b333012ce3a1718cd8ad493b90695734350ac345c42c911d5038b9f288d2d5da8e1bafe1f22967eef3f705a49310f7ebb0837303ede480564cbd5174d354c15668846ed5e9b40002f831d118aeb1d78fd41a9e80064da3bc0f84fe0898e0e2d81cf20a14baebb1f1d784682fce429625f6a8999177f9e1adf515638280279f5dbbb8eff1fb09ba3782cb6bb49ae28b38883808c69c70a45cf2efb5932c67c77756a9eae3cc63cab0f3554cc55e6fe6f1d1fe6a7fd27c248fa0f491a5c459c0e51bc06d9574cb22c1c4d5aa64b4b66875233bbdd"}}, +}, +}; + +static const struct cgo_client_originate_testvec { + cgo_tv_state_t state_in[3]; + int target_hop; + const char *cmd; + const char *msg; + struct { + cgo_tv_state_t state[3]; + struct { + const char *t_out; + const char *msg_out; + } result; + } output; +} CGO_CLIENT_ORIGINATE_TESTVECS[] = { +// All zeros, hop 3/3 +{ + // S{} + {{"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000"}, {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000"}, {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000"}}, + // d + 3, + // AD + "00", + // M + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + // Output={S'{}, T, C} + {{{"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", "af65bb470269ecd7af01f68f1a2b7b78"}, {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "00000000000000000000000000000000", "140f0f1011b5223d79587717ffd9ec3a"}, {"7941dd0a63d994703e63d94a446804213ab4fb1d2b7ba376590a2c241d1f508dc6a7f418a14503deb89b17aadb2806f73fc06e5d14e675f5ec880023d4f73296", "12dce4a0e5bc792b5b5a55f9c2f30e07", "00000000000000000000000000000000"}}, {"1471e71e6fb1f04233a8ec5daa6209e0", "66e94bd4ef8a2c3b884cfa59ca342b2e58e2fccefa7e3061367f1d57a4e7455a0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40deb3fa6794f8fd8f55a88dcbda9d68f2137cc9c83420077e7cf28ab2696b0df05d11452b58ac50aa2eb3a195b61b87e5c65a6dd5d7f7a84065d5a17ff46273086002496db63fa4b91bee387fa3030c95a73f8d0437e0915fbce5d7a62d8dab0a58b2431bc0bede02550f40238969ec780410befccde6944b69dd007debe39a9dbc5e24f519a4bdf478b1d9ec0b67125f28b06efaa55d79412ad628d45089c3c304f94db3a21df6cdaf6d2e2e3b355441eff64ad90527e752a4b2ebb4d0a1070ce2e2982e272fdb7cf4b584b095a0f957fdb828689437e37dc48b2ad379c6f3c6e957ee77afb88c65949ba12eec45c22865e4907ae42aee813898acdf91e2e4c21d828e0a76de2bb6bb6f869e5eef1f618dedd27562812b9a14e8996a5c352df3817e60d6ec20119a52c80a61ec195622627240212decca515feab63e2734587948a836a7de205cfec0c288351c"}}, +}, +// All ones, hop 3/3 +{ + // S{} + {{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff"}, {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff"}, {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff"}}, + // d + 3, + // AD + "ff", + // M + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + // Output={S'{}, T, C} + {{{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff", "3cf25f81c98d0be16ddbbffeefbdc308"}, {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffff", "a9166add184e00b007217cb4e4f52ee5"}, {"be938fc23009440bfb5d7bba1d28428ec0897793bb878b8e1eb3ec1257b88024d551d770b56c9312de3dd4ac64e194c91185a89f2ba01f90b03b3acb93f634df", "4b263f03af0acda2f9721d0f4c0783c7", "ffffffffffffffffffffffffffffffff"}}, {"c8c388584500c58ced7ee209c08b920a", "c0685473f8558a9f9f2f22cfb31f211c6b25b7ebdabf2507b4269636caa01e1f6d4f4f5690c48d6940361059b37516b52b9d9ad93388f964666e7492a6adb91645a02cf39eed4ebd0354d8f484106c04ebb0e53d858c75a44e3145471bf93d09d48af913fdcefa6a0dd3fb730e604035d494f0a5706c3b63424253b7287392a44e9b2f66f765dd7cda20c76a2444a4dfa84170d810eb13e720867170c243ff4d9662b1df15b826c664f1a52e4f57be57b49105895e8ae3b87fd969034f67ae9784d946935dac622cb4cf786ad937174ceab2c766be361f8efc0479aa0b45c5e90da1dcee6802b5acf53dfee7a12e27d55e832b5f77360cd7190522d9057a556b8e1de773a0c29cc20c44dd963395cce1c19633fe1e386a3cc87082d5e645914d96ce3d8dcb9653dedacd8bfc2fe5d7a3e9e205a9c0961dd83d5b5515842fa3291877146081d5d776c4675de92b3f92edd80d7792b9a9f203c6650a33e54822d45a92c7136cf4fdbe6fe698ed6d3596cce17853aa988142a5925e1cd4382fb4d43307c26d57676c1ae5aaec6100de8414f8fc763e87a052f3d7519d539499d90f427c951d91348d9f0c7d77dd454bd8cd80b9b13a1870f95ea19e8dbdfd78ca4cfd520e5bcfcbd751252775165790b250b0d87989a60ccbd4243f8409a28d1d0536d9d9ad51ee474d24a92870b7"}}, +}, +// Pesudorandom 1, hop 1/3 +{ + // S{} + {{"80819c55d001b73b8d51a5c9ce4fc8e2a197bd4891f0f38df791e92fc687c99214992b6749f5b96d6477f7a2821029f714de39b47396fff84b79406ceb667213", "475cec821a2bb29682c9de4ed89fa2bc", "63c839b54659920bbf42c8a76eedc3a9"}, {"79d6e9f34cd2a01b89130bc43002e94a4c3494dfc8db9d11e08d7b8ae7782b38fde2c00e9819d5c619a5c8a92afbabdb727108b5dd4ba9d572b47567685c9e7c", "d6dc99f4ce27ffe7ad3b40c73be86ad8", "eae6b850f1f43e00be741946b5038517"}, {"cc01d778ccfabfad7a442a266aac199e277b38618ba19816d1d668c139367c8ae4c9fc4e6b5a7a214175506d4dffa1c159bc499afc638e6a54a546380b65bcd8", "e459433194d5ce2daf958ef6cb22a391", "34df2febf45efcb197fabf5eef51bf5e"}}, + // d + 1, + // AD + "00", + // M + "32b9e80d44f7fd35dc254f1b07cd10ca91e1c9ba7835a9581e99245677c1ecec22de4e30ef1799ab658305c8266d4f1c71e4ad51cd9d5798de85ece04f6ee9636ad4a14a132278df2c34a449b7d53cf71fb4e55affbc7cbc6699b97356a81d4f70591177aa509df7d8ada37bd7c6082059081e8058087bd5e357544b2b2067c62a3cb123592b44bef8ccb5f259e859ac8d6c9cf599605b370a067dced095f96dd03b3577d20b78afeb8c25cbe3b2e52f2105e952603af981a739216fc6fa29f1a417ea501199a74bab8821e828a1e66e8e0de40138aca846902f7e2c5545cb2263a8b148e65fd793abbd831d97771d5ecbc07bcde5b5cfa02489783302174b36f7570c546fcb05b1d1031089b806d9b54d2b0ebf0fa0ce8b486e26c36825b55a1bcdd001b4a6ab3686ae3b5fef3500837a1eb58e44602c87ce6d384d3dab73fc18e662f03a4112c6fd70ee2063a5dd37bc159f2584b8bcc63106ff6f219cb3e45d57e3b78c88fb0acbba7b58f2f3c54d1877160199583876e1a321bfaa813e0ce1e1803fff094e437ca879ab2d85248050f720bfac980a8455f1bd83ad8648af0052a3ff1203a75b033254edcbfc144c53ec72b603b404aac06021d51524953e9d267c912cc82d61b70d47775d80451ae59071ce7596f3dfe60ff0f636ec06689993ed52f8efd7d04415350421", + // Output={S'{}, T, C} + {{{"d0f4674c280810a523aa25f98bbcff032b4f78f536ab763365384c3f55117e26da677483b85954db5e0840ee66ed269c7089e404f881dea4ecfa1619ca809444", "2b6b31a8b26936bf1823ea99b866d000", "475cec821a2bb29682c9de4ed89fa2bc"}, {"79d6e9f34cd2a01b89130bc43002e94a4c3494dfc8db9d11e08d7b8ae7782b38fde2c00e9819d5c619a5c8a92afbabdb727108b5dd4ba9d572b47567685c9e7c", "d6dc99f4ce27ffe7ad3b40c73be86ad8", "eae6b850f1f43e00be741946b5038517"}, {"cc01d778ccfabfad7a442a266aac199e277b38618ba19816d1d668c139367c8ae4c9fc4e6b5a7a214175506d4dffa1c159bc499afc638e6a54a546380b65bcd8", "e459433194d5ce2daf958ef6cb22a391", "34df2febf45efcb197fabf5eef51bf5e"}}, {"7d05e89f33820206b821fdd7a7465525", "f97feaae58ac1c0e4a69df97b1da3641d0c8795a1ab5e957d94629b9b181129b58bdc5df73588c0068bc67ef14a50d8cb8dd1dce8c1c5ff6b7a0616bbde921f442dd876b3622f88918ba01234920759d4ec3f1079f4d5029b9903fd2b9c60540b89b59134c36b64b58509791cb6b3074f84fed410f27cd4d868a9cb59df2ebe9e3358ed557c4ed2d91e7f3080468734df02536d5e30c27d4021d5ce00eb38b08cde074587fb321510139c4d865da92a4b0ba3833d8b110e3c81e3226099677f91f570add37f6867e9faae6331bc0ca19e475ac75d8dd688b1d77cfa5c28f3e0838bb3f8457bbe7bfb567826cf42913108c268d710253c74dc09def9885c61a3e0ca65231121d746a720d0f6454d09613e9620c0ffe922be22aae5c7e5ac17b083cff28c48c1c205834880689df9dfc5085775695ac3931dce1b05a669c96664fcdb86794d3883de5f9396c351ef26880f8f5d1f64bde7c73fdf177363343a37497de8e9aa4e139c196c9069e4b9a4cfc71e89a8deb80a2a1810e9584002f3d054e64c7e3afd7f215cdac0ea35ae8e6e88c290006ef80c1a193be34f89ac8ac8f03971c2d8f35fa0ceddf9a34d9482bc9cb9787faf942606131abcce19b6ab1aba23bd45c31d15e1189987114f507661916aae148f80b03a3d769a277ca9ce8c2e9d46f4b58319a72627eba3024"}}, +}, +// Pesudorandom 1, hop 3/3 +{ + // S{} + {{"80819c55d001b73b8d51a5c9ce4fc8e2a197bd4891f0f38df791e92fc687c99214992b6749f5b96d6477f7a2821029f714de39b47396fff84b79406ceb667213", "475cec821a2bb29682c9de4ed89fa2bc", "63c839b54659920bbf42c8a76eedc3a9"}, {"79d6e9f34cd2a01b89130bc43002e94a4c3494dfc8db9d11e08d7b8ae7782b38fde2c00e9819d5c619a5c8a92afbabdb727108b5dd4ba9d572b47567685c9e7c", "d6dc99f4ce27ffe7ad3b40c73be86ad8", "eae6b850f1f43e00be741946b5038517"}, {"cc01d778ccfabfad7a442a266aac199e277b38618ba19816d1d668c139367c8ae4c9fc4e6b5a7a214175506d4dffa1c159bc499afc638e6a54a546380b65bcd8", "e459433194d5ce2daf958ef6cb22a391", "34df2febf45efcb197fabf5eef51bf5e"}}, + // d + 3, + // AD + "00", + // M + "32b9e80d44f7fd35dc254f1b07cd10ca91e1c9ba7835a9581e99245677c1ecec22de4e30ef1799ab658305c8266d4f1c71e4ad51cd9d5798de85ece04f6ee9636ad4a14a132278df2c34a449b7d53cf71fb4e55affbc7cbc6699b97356a81d4f70591177aa509df7d8ada37bd7c6082059081e8058087bd5e357544b2b2067c62a3cb123592b44bef8ccb5f259e859ac8d6c9cf599605b370a067dced095f96dd03b3577d20b78afeb8c25cbe3b2e52f2105e952603af981a739216fc6fa29f1a417ea501199a74bab8821e828a1e66e8e0de40138aca846902f7e2c5545cb2263a8b148e65fd793abbd831d97771d5ecbc07bcde5b5cfa02489783302174b36f7570c546fcb05b1d1031089b806d9b54d2b0ebf0fa0ce8b486e26c36825b55a1bcdd001b4a6ab3686ae3b5fef3500837a1eb58e44602c87ce6d384d3dab73fc18e662f03a4112c6fd70ee2063a5dd37bc159f2584b8bcc63106ff6f219cb3e45d57e3b78c88fb0acbba7b58f2f3c54d1877160199583876e1a321bfaa813e0ce1e1803fff094e437ca879ab2d85248050f720bfac980a8455f1bd83ad8648af0052a3ff1203a75b033254edcbfc144c53ec72b603b404aac06021d51524953e9d267c912cc82d61b70d47775d80451ae59071ce7596f3dfe60ff0f636ec06689993ed52f8efd7d04415350421", + // Output={S'{}, T, C} + {{{"80819c55d001b73b8d51a5c9ce4fc8e2a197bd4891f0f38df791e92fc687c99214992b6749f5b96d6477f7a2821029f714de39b47396fff84b79406ceb667213", "475cec821a2bb29682c9de4ed89fa2bc", "959551c3e8dc83f3cf2e0bf11a1acae3"}, {"79d6e9f34cd2a01b89130bc43002e94a4c3494dfc8db9d11e08d7b8ae7782b38fde2c00e9819d5c619a5c8a92afbabdb727108b5dd4ba9d572b47567685c9e7c", "d6dc99f4ce27ffe7ad3b40c73be86ad8", "9e9c84b867f7dbeb705bfcce09431813"}, {"12f2e45f012ffc1430fee1fb322879ba934f887fe2e7e7ce98071c61bc1086dbb2877845f5fb3869d3a4d23cdbcb44c85aeb9e43771755c9be3bbdb42ecac024", "88ba0caf597d953a26064c5872bdea5b", "e459433194d5ce2daf958ef6cb22a391"}}, {"3222f41f846157bdc258ac55d8f7bd6e", "fb76e827b3a0b6b8d031ea07b273c8f47763cd2c7af610dd0109ff42838bc39d5128492788a36426fc5ab17bab4906c7c4a390ceabe14ccc96ac2ec36dac92ed2a579097d1cb2258aef9cf35e950113adbb305b7ac73e1c1ea9b4e10ff39adc6b129cad8020fdcb349fd383595c61bb551d026b84ed74674bcfbbe027b4814713487a53e5aac4120da59d27b0abce7f438294860c211f19160b53deb9ab5abf49996a1d474518196a1020b460282f9dc3802db33c19e3b50d74fc5f8083403227d9801a158977f36cb2eae1525488660b59e5f45f346f24def7044f1b8e714268ff423d8c9b895e936669b4df15a99ba6382b02349f792b2383a4bd632efb6b6a5b7cbb82eaae1b0261f5386844813f23e08eeb68d63162681d51bf0d38beff2c34afc2e57772887f5c0e341ff2b7c003b24d32bb3873c7f6d5b946c36b18eb0ddfe907c201cd42b7373eb52d0c4bd8eed5179a2081504847f7f99fe529139cdde799105e8c05cf8376eaddf4af1f779835910659ff93ad3f55b25defbcc10567d23247a0f2e688363f91f90184cda34d8e4ad80d4f9f47d9d1af9c10474f7e66bef3ad0a49fbdc8020899289bea741a004df514b8ec5bf2443e3de433cd25916b2889fe6a624e65c4b1306d9feb14fbad48e2c212cb4aa8db92c31b87c20da5b493410fdafaab09fdfb57c9aa"}}, +}, +// Pesudorandom 2, hop 2/3 +{ + // S{} + {{"f2a93dfda00e7654585b911e90acdc3a825f88b497f329637bb612464d928e4182f1b360db55231f255e7265b1614d8ee895cde4e5f4768f749c051b25ac261e", "6a017e1dfd3fcee547b526b048204901", "7dae89533c98d159590a3bc5da3d5fb6"}, {"ff9b9925190d45c46e5ac9eae38da326739b3180432cf0c36cd9346699bd022c4dcb3aa2811f8ab0a2a72cfdc9e13b817d0a20cc1b03f51b8133c6d36d2c4ffa", "2e666844518d40d4a1efee952db70f36", "eeb1f87fd5c7a6b016b6df886c3f2f92"}, {"25f3b6dc37742bf020ad710e67f87ee274f5fe5d0c75c9a22da939847d1f4878de7d35867c306f3176d92d2d5900d33dec007edf02644f01046b9deff015c30f", "df6876f95d2387d8f419d018a826ffed", "c16980670fba6dcd755c567c721e0dcd"}}, + // d + 2, + // AD + "da", + // M + "346681ef9e47fff29ddaf41628ae3021888028316787f1887b6c099c921a8915b4d7937a9565d928764fae620b57d117ccd75cf8b633f2d1f1404b65f2479c8d8d590a15da2b40b14987d8968b7d210965f158627a72ba31ccecd5727f2dabf17dacc69027ccf4c53da96a75e6d28a15ffecaec1965a62402a1cc5e9cc26be181689132f54956f99192ac9bbb929c5aec7048a6653ad40cbc4fb029ea97bc15c8b05395e822af36a8b949817ee0f022c8f971eefc5b31bb46e095d4aea07fa97854e1ca4a208bebb65a605089f60a21ef5685b67d312edff8b2cc81830eab9d27ab0a7be29b7c88abb995492564772d518a912c6b40f58ab41c0497995d9b593f0387a3e597728d08f5267fba8370a062817cdf506119e0c5cc69900709195a2288322de578af491698360ad1f6b34b341e10eb21e22f6c5a6e12e26250aeb528aaa533d592b268fb22b3e77ada84d478ee9d0f2742cbb54be14503c21e39efcc73774b24bf28747203c5ff456457139fec8a46c8243b4b9738c27972e6d8f0ef9fa18944aaeed4deb437522f04795ecd7bee79f0a6d7c6c6acd90dac9a935d5f252134cd4ca1e2e0c4386fdae67950f1234cda5472e61a32bf9f037c068fe81a955d1e56a92ad1a8f16e6a31bfc0f8b3cef96410a72b92a75b09a0071ff0c0e99dd322ab7d8e4a2a2c2122af6", + // Output={S'{}, T, C} + {{{"f2a93dfda00e7654585b911e90acdc3a825f88b497f329637bb612464d928e4182f1b360db55231f255e7265b1614d8ee895cde4e5f4768f749c051b25ac261e", "6a017e1dfd3fcee547b526b048204901", "2d8aa5329c2fab108e90f64a904c4def"}, {"64b7371338ad74c249ba606c677f38b5c08ba69a7ae33c1be26ef81ea604a24a968678f48075273c6b35311642a72466fd2a6b059217f66752b0c9e15de40a5f", "5f6d3291d9d5bf3c3bece127fbf3886b", "2e666844518d40d4a1efee952db70f36"}, {"25f3b6dc37742bf020ad710e67f87ee274f5fe5d0c75c9a22da939847d1f4878de7d35867c306f3176d92d2d5900d33dec007edf02644f01046b9deff015c30f", "df6876f95d2387d8f419d018a826ffed", "c16980670fba6dcd755c567c721e0dcd"}}, {"9527488f5d1c2671e0e8139423149285", "c036126d33eea9f7cf865a9ab8e8eaace3a59f1064fa7506d45862ceb119ed854e1ab2f4294c77beb60564e2095f1f219dac41a024361e0fce045947a5e104a6db4b35175b09fca762121d46be7b4b20c674e4a13a53585586c8318549b86c02db4a554e1a43674237136f91e91e75c7ef74e6d4bceeb682e27ffbd2f47ddf667ad89fea7c48e6fbe69b8a3e54eb31585612719394480416296689d427a59b0f3adf4d92fa239c983a2c010cffe9366c01a1c945757ba07aec7c3df58b95f567e8de04d5719c2c7c62cd44668d43777b87db9126b2fccb62b241ec9d9701e8a34125a4dc2653a3de1f77415cafa76bc2713bed61c44001fb23170d716d008f12b236c0380253f2779fe52e6b2c011ffe312617b149c0b2b47055dc832ead1b297ead29028a4a0dbed96809c2aede9b276458a8a6c142a6a7876de3cfba1d4d0dea00095a66b9e925a3593b956a7e734b074941fc60d656e27a7d24f196cfe928400a180a1b7eb591c7b4e394b2c13040a98612e078094586bb197a585505335f4b5f1f721df1ee76ef27a8f6927fc40077be55a45b093d4fa1057a4a88937174885732f91d04a87424539302c7f9590e4d0b62abfdbd0f162fa3c7d750b8f212a2612127fd2443416736578deeccc76284c164a282f94786812031a19f35629e253a86c730f08676fbd0b0b41d"}}, +}, +// Pesudorandom 2, hop 3/3 +{ + // S{} + {{"f2a93dfda00e7654585b911e90acdc3a825f88b497f329637bb612464d928e4182f1b360db55231f255e7265b1614d8ee895cde4e5f4768f749c051b25ac261e", "6a017e1dfd3fcee547b526b048204901", "7dae89533c98d159590a3bc5da3d5fb6"}, {"ff9b9925190d45c46e5ac9eae38da326739b3180432cf0c36cd9346699bd022c4dcb3aa2811f8ab0a2a72cfdc9e13b817d0a20cc1b03f51b8133c6d36d2c4ffa", "2e666844518d40d4a1efee952db70f36", "eeb1f87fd5c7a6b016b6df886c3f2f92"}, {"25f3b6dc37742bf020ad710e67f87ee274f5fe5d0c75c9a22da939847d1f4878de7d35867c306f3176d92d2d5900d33dec007edf02644f01046b9deff015c30f", "df6876f95d2387d8f419d018a826ffed", "c16980670fba6dcd755c567c721e0dcd"}}, + // d + 3, + // AD + "da", + // M + "346681ef9e47fff29ddaf41628ae3021888028316787f1887b6c099c921a8915b4d7937a9565d928764fae620b57d117ccd75cf8b633f2d1f1404b65f2479c8d8d590a15da2b40b14987d8968b7d210965f158627a72ba31ccecd5727f2dabf17dacc69027ccf4c53da96a75e6d28a15ffecaec1965a62402a1cc5e9cc26be181689132f54956f99192ac9bbb929c5aec7048a6653ad40cbc4fb029ea97bc15c8b05395e822af36a8b949817ee0f022c8f971eefc5b31bb46e095d4aea07fa97854e1ca4a208bebb65a605089f60a21ef5685b67d312edff8b2cc81830eab9d27ab0a7be29b7c88abb995492564772d518a912c6b40f58ab41c0497995d9b593f0387a3e597728d08f5267fba8370a062817cdf506119e0c5cc69900709195a2288322de578af491698360ad1f6b34b341e10eb21e22f6c5a6e12e26250aeb528aaa533d592b268fb22b3e77ada84d478ee9d0f2742cbb54be14503c21e39efcc73774b24bf28747203c5ff456457139fec8a46c8243b4b9738c27972e6d8f0ef9fa18944aaeed4deb437522f04795ecd7bee79f0a6d7c6c6acd90dac9a935d5f252134cd4ca1e2e0c4386fdae67950f1234cda5472e61a32bf9f037c068fe81a955d1e56a92ad1a8f16e6a31bfc0f8b3cef96410a72b92a75b09a0071ff0c0e99dd322ab7d8e4a2a2c2122af6", + // Output={S'{}, T, C} + {{{"f2a93dfda00e7654585b911e90acdc3a825f88b497f329637bb612464d928e4182f1b360db55231f255e7265b1614d8ee895cde4e5f4768f749c051b25ac261e", "6a017e1dfd3fcee547b526b048204901", "d0c6f32d192ad998d5fa04b32a872f8e"}, {"ff9b9925190d45c46e5ac9eae38da326739b3180432cf0c36cd9346699bd022c4dcb3aa2811f8ab0a2a72cfdc9e13b817d0a20cc1b03f51b8133c6d36d2c4ffa", "2e666844518d40d4a1efee952db70f36", "c0ae73b766ba40692b47a08c07265205"}, {"7e710ab0fcc90e1919c4996abac395e440e26eadf2df429defc893bfa97eedc55afa0504c9cee635bb933013d5d1fd54ddd30d5dc8fedcc5b55368837e00c085", "43d445810df84f486bdbe4d69637633f", "df6876f95d2387d8f419d018a826ffed"}}, {"0e49b626343b62d9155ffca96b076d70", "d64d402225cfc1e55c277c5827d8fea52c683693568928ad817bdb161852f9bbb6b316c78c4ef24d3b2620bd584e128e709a399a6c320ab5943816d786a0b7d81f0023b522ebac91e4fc79d9f6b3f5dcc22f17f486ef93518e2f885327ebac19daaaa3998dfdcb5880d76a196a8bba54a0b9169427d1f83abf95fcc8f63dfeb03d50d083e11c38a55d2efbe2c607648a5caa3698393faaaf339ca1d4c48cab8184ec20d8dc4ad03793ff1806b802e932c33f00fa0253bc7da8fa560b19cac163bbf26e4507642fcc39b5df28b3941fccbd30e3e00b64f471a51d7555c3d1b6655b0a6d9d33b9cd0494163591675c50ebb5a867e849a9c6ee43a177d7fe9f6aa992c817b26316054b49894f973ae166fb20f2bfc50704f610e2cc61be08e1305fa58f15b716aaacb50c98e0dba34a300a1aa4296f7826f0ad740f36eef6d18205b1118227c285acef158b4093dd541eed76a3492240be48e89fa54cad77b020631413a8b562e655289f94191bc462b71ddf0b41a034ca1c291aa4feb0148207e2ea0d5409e801dcec151b0a5a220ac43b8be70c8c92d6eb4f9c6f44bf0fd3487c5d007ba8ddd8bbbca51fb3c679ffc0a493392039f32e7272f173e71d4a2a5f001f999dd9523c79ca3e32c99260b20f1e960a830bd7ed81d891c316c8851b3470c64b7fb15d7ebdb8d09399e74f"}}, +}, +}; diff -Nru tor-0.4.8.16/src/test/compression_bomb.h tor-0.4.9.6/src/test/compression_bomb.h --- tor-0.4.8.16/src/test/compression_bomb.h 1970-01-01 00:00:00.000000000 +0000 +++ tor-0.4.9.6/src/test/compression_bomb.h 2026-03-25 14:30:34.000000000 +0000 @@ -0,0 +1,864 @@ +/* Copyright (c) 2007-2026, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_TEST_COMPRESSION_BOMB_H +#define TOR_TEST_COMPRESSION_BOMB_H + +const char compression_bomb_gzip[] = { + 0x1f, 0x8b, 0x08, 0x00, 0x75, 0x27, 0xdd, 0x68, 0x02, 0x03, 0xec, 0xc1, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x80, 0x90, 0xfe, 0xaf, 0xee, 0x08, 0x0a, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xd9, 0x83, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, + 0xff, 0xd7, 0x46, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x69, 0x0f, 0x0e, 0x09, 0x00, + 0x00, 0x00, 0x00, 0x04, 0xfd, 0x7f, 0xed, 0x0c, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9f, + 0x00, 0xcc, 0x2a, 0xca, 0x9e, 0x00, 0x00, 0xa0, 0x00 +}; + +const size_t compression_bomb_gzip_len = 10221; + +#endif /* !defined(TOR_TEST_COMPRESSION_BOMB_H) */ diff -Nru tor-0.4.8.16/src/test/fakecircs.c tor-0.4.9.6/src/test/fakecircs.c --- tor-0.4.8.16/src/test/fakecircs.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/fakecircs.c 2026-03-25 14:30:34.000000000 +0000 @@ -22,7 +22,7 @@ #include "core/or/conflux.h" #include "core/or/crypt_path.h" #include "core/or/relay.h" -#include "core/or/relay_crypto_st.h" +#include "core/crypto/relay_crypto_st.h" #include "test/fakecircs.h" @@ -59,8 +59,9 @@ cell_queue_init(&(orcirc->p_chan_cells)); memset(&tmp_cpath, 0, sizeof(tmp_cpath)); - if (cpath_init_circuit_crypto(&tmp_cpath, whatevs_key, - sizeof(whatevs_key), 0, 0)<0) { + if (cpath_init_circuit_crypto(RELAY_CRYPTO_ALG_TOR1, + &tmp_cpath, whatevs_key, + sizeof(whatevs_key))<0) { log_warn(LD_BUG,"Circuit initialization failed"); return NULL; } diff -Nru tor-0.4.8.16/src/test/include.am tor-0.4.9.6/src/test/include.am --- tor-0.4.8.16/src/test/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -22,14 +22,14 @@ src/test/test_switch_id.sh \ src/test/test_cmdline.sh \ src/test/test_parseconf.sh \ - src/test/unittest_part1.sh \ - src/test/unittest_part2.sh \ - src/test/unittest_part3.sh \ - src/test/unittest_part4.sh \ - src/test/unittest_part5.sh \ - src/test/unittest_part6.sh \ - src/test/unittest_part7.sh \ - src/test/unittest_part8.sh + src/test/unittest_part1.sh \ + src/test/unittest_part2.sh \ + src/test/unittest_part3.sh \ + src/test/unittest_part4.sh \ + src/test/unittest_part5.sh \ + src/test/unittest_part6.sh \ + src/test/unittest_part7.sh \ + src/test/unittest_part8.sh if USEPYTHON TESTSCRIPTS += \ @@ -51,7 +51,7 @@ if USE_PERL TESTSCRIPTS += \ - scripts/maint/checkSpaceTest.sh + scripts/maint/checkSpaceTest.sh endif TESTS += src/test/test-slow src/test/test-memwipe \ @@ -103,8 +103,8 @@ src_test_AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ -DLOCALSTATEDIR="\"$(localstatedir)\"" \ - -DBINDIR="\"$(bindir)\"" \ - -DTOR_UNIT_TESTS \ + -DBINDIR="\"$(bindir)\"" \ + -DTOR_UNIT_TESTS \ $(AM_CPPFLAGS) # -L flags need to go in LDFLAGS. -l flags need to go in LDADD. @@ -162,6 +162,7 @@ src/test/test_crypto.c \ src/test/test_crypto_ope.c \ src/test/test_crypto_rng.c \ + src/test/test_crypto_cgo.c \ src/test/test_data.c \ src/test/test_dir.c \ src/test/test_dirauth_ports.c \ @@ -336,7 +337,7 @@ src_test_bench_LDFLAGS = @TOR_LDFLAGS_zlib@ $(TOR_LDFLAGS_CRYPTLIB) \ @TOR_LDFLAGS_libevent@ src_test_bench_LDADD = \ - libtor.a \ + libtor.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \ $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ @CURVE25519_LIBS@ \ @@ -365,6 +366,7 @@ # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS+= \ + src/test/compression_bomb.h \ src/test/fakechans.h \ src/test/fakecircs.h \ src/test/hs_test_helpers.h \ @@ -382,6 +384,7 @@ src/test/example_extrainfo.inc \ src/test/failing_routerdescs.inc \ src/test/ed25519_vectors.inc \ + src/test/cgo_vectors.inc \ src/test/test_descriptors.inc \ src/test/test_hs_descriptor.inc \ src/test/vote_descriptors.inc @@ -404,11 +407,10 @@ libtor.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ $(TOR_LIBS_CRYPTLIB) @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ \ - @CURVE25519_LIBS@ @TOR_TRACE_LIBS@ + @CURVE25519_LIBS@ @TOR_TRACE_LIBS@ src_test_test_hs_ntor_cl_AM_CPPFLAGS = \ $(AM_CPPFLAGS) - if UNITTESTS_ENABLED noinst_PROGRAMS += src/test/test-bt-cl src_test_test_bt_cl_SOURCES = src/test/test_bt_cl.c @@ -416,7 +418,7 @@ $(TOR_UTIL_TESTING_LIBS) \ @TOR_LIB_MATH@ \ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @TOR_LIB_USERENV@ \ - @TOR_TRACE_LIBS@ + @TOR_TRACE_LIBS@ src_test_test_bt_cl_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) src_test_test_bt_cl_CPPFLAGS= $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) endif @@ -438,7 +440,8 @@ src/test/test_keygen.sh \ src/test/test_key_expiration.sh \ src/test/test_zero_length_keys.sh \ - src/test/test_ntor.sh src/test/test_hs_ntor.sh src/test/test_bt.sh \ + src/test/test_ntor.sh src/test/test_hs_ntor.sh \ + src/test/test_bt.sh \ src/test/test-network.sh \ src/test/test_switch_id.sh \ src/test/test_workqueue_cancel.sh \ @@ -449,11 +452,11 @@ src/test/test_workqueue_socketpair.sh \ src/test/test_cmdline.sh \ src/test/test_parseconf.sh \ - src/test/unittest_part1.sh \ - src/test/unittest_part2.sh \ - src/test/unittest_part3.sh \ - src/test/unittest_part4.sh \ - src/test/unittest_part5.sh \ - src/test/unittest_part6.sh \ - src/test/unittest_part7.sh \ - src/test/unittest_part8.sh + src/test/unittest_part1.sh \ + src/test/unittest_part2.sh \ + src/test/unittest_part3.sh \ + src/test/unittest_part4.sh \ + src/test/unittest_part5.sh \ + src/test/unittest_part6.sh \ + src/test/unittest_part7.sh \ + src/test/unittest_part8.sh diff -Nru tor-0.4.8.16/src/test/test.c tor-0.4.9.6/src/test/test.c --- tor-0.4.8.16/src/test/test.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test.c 2026-03-25 14:30:34.000000000 +0000 @@ -50,7 +50,6 @@ #include "core/or/onion.h" #include "core/crypto/onion_ntor.h" #include "core/crypto/onion_fast.h" -#include "core/crypto/onion_tap.h" #include "core/or/policies.h" #include "lib/sandbox/sandbox.h" #include "app/config/statefile.h" @@ -61,150 +60,6 @@ #include "core/or/or_circuit_st.h" #include "feature/relay/onion_queue.h" -/** Run unit tests for the onion handshake code. */ -static void -test_onion_handshake(void *arg) -{ - /* client-side */ - crypto_dh_t *c_dh = NULL; - char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN]; - char c_keys[40]; - /* server-side */ - char s_buf[TAP_ONIONSKIN_REPLY_LEN]; - char s_keys[40]; - int i; - /* shared */ - crypto_pk_t *pk = NULL, *pk2 = NULL; - - (void)arg; - pk = pk_generate(0); - pk2 = pk_generate(1); - - /* client handshake 1. */ - memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN); - tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf)); - - for (i = 1; i <= 3; ++i) { - crypto_pk_t *k1, *k2; - if (i==1) { - /* server handshake: only one key known. */ - k1 = pk; k2 = NULL; - } else if (i==2) { - /* server handshake: try the right key first. */ - k1 = pk; k2 = pk2; - } else { - /* server handshake: try the right key second. */ - k1 = pk2; k2 = pk; - } - - memset(s_buf, 0, TAP_ONIONSKIN_REPLY_LEN); - memset(s_keys, 0, 40); - tt_assert(! onion_skin_TAP_server_handshake(c_buf, k1, k2, - s_buf, s_keys, 40)); - - /* client handshake 2 */ - memset(c_keys, 0, 40); - tt_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, - 40, NULL)); - - tt_mem_op(c_keys,OP_EQ, s_keys, 40); - memset(s_buf, 0, 40); - tt_mem_op(c_keys,OP_NE, s_buf, 40); - } - done: - crypto_dh_free(c_dh); - crypto_pk_free(pk); - crypto_pk_free(pk2); -} - -static void -test_bad_onion_handshake(void *arg) -{ - char junk_buf[TAP_ONIONSKIN_CHALLENGE_LEN]; - char junk_buf2[TAP_ONIONSKIN_CHALLENGE_LEN]; - /* client-side */ - crypto_dh_t *c_dh = NULL; - char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN]; - char c_keys[40]; - /* server-side */ - char s_buf[TAP_ONIONSKIN_REPLY_LEN]; - char s_keys[40]; - /* shared */ - crypto_pk_t *pk = NULL, *pk2 = NULL; - - (void)arg; - - pk = pk_generate(0); - pk2 = pk_generate(1); - - /* Server: Case 1: the encrypted data is degenerate. */ - memset(junk_buf, 0, sizeof(junk_buf)); - crypto_pk_obsolete_public_hybrid_encrypt(pk, - junk_buf2, TAP_ONIONSKIN_CHALLENGE_LEN, - junk_buf, DH1024_KEY_LEN, - PK_PKCS1_OAEP_PADDING, 1); - tt_int_op(-1, OP_EQ, - onion_skin_TAP_server_handshake(junk_buf2, pk, NULL, - s_buf, s_keys, 40)); - - /* Server: Case 2: the encrypted data is not long enough. */ - memset(junk_buf, 0, sizeof(junk_buf)); - memset(junk_buf2, 0, sizeof(junk_buf2)); - crypto_pk_public_encrypt(pk, junk_buf2, sizeof(junk_buf2), - junk_buf, 48, PK_PKCS1_OAEP_PADDING); - tt_int_op(-1, OP_EQ, - onion_skin_TAP_server_handshake(junk_buf2, pk, NULL, - s_buf, s_keys, 40)); - - /* client handshake 1: do it straight. */ - memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN); - tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf)); - - /* Server: Case 3: we just don't have the right key. */ - tt_int_op(-1, OP_EQ, - onion_skin_TAP_server_handshake(c_buf, pk2, NULL, - s_buf, s_keys, 40)); - - /* Server: Case 4: The RSA-encrypted portion is corrupt. */ - c_buf[64] ^= 33; - tt_int_op(-1, OP_EQ, - onion_skin_TAP_server_handshake(c_buf, pk, NULL, - s_buf, s_keys, 40)); - c_buf[64] ^= 33; - - /* (Let the server proceed) */ - tt_int_op(0, OP_EQ, - onion_skin_TAP_server_handshake(c_buf, pk, NULL, - s_buf, s_keys, 40)); - - /* Client: Case 1: The server sent back junk. */ - const char *msg = NULL; - s_buf[64] ^= 33; - tt_int_op(-1, OP_EQ, - onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg)); - s_buf[64] ^= 33; - tt_str_op(msg, OP_EQ, "Digest DOES NOT MATCH on onion handshake. " - "Bug or attack."); - - /* Let the client finish; make sure it can. */ - msg = NULL; - tt_int_op(0, OP_EQ, - onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg)); - tt_mem_op(s_keys,OP_EQ, c_keys, 40); - tt_ptr_op(msg, OP_EQ, NULL); - - /* Client: Case 2: The server sent back a degenerate DH. */ - memset(s_buf, 0, sizeof(s_buf)); - tt_int_op(-1, OP_EQ, - onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg)); - tt_str_op(msg, OP_EQ, "DH computation failed."); - - done: - crypto_dh_free(c_dh); - crypto_pk_free(pk); - crypto_pk_free(pk2); -} - static void test_ntor_handshake(void *arg) { @@ -221,7 +76,8 @@ /* shared */ const curve25519_public_key_t *server_pubkey; - uint8_t node_id[20] = "abcdefghijklmnopqrst"; + + NONSTRING uint8_t node_id[20] = "abcdefghijklmnopqrst"; (void) arg; @@ -306,37 +162,35 @@ static void test_onion_queues(void *arg) { - uint8_t buf1[TAP_ONIONSKIN_CHALLENGE_LEN] = {0}; + uint8_t buf1[NTOR_ONIONSKIN_LEN] = {0}; uint8_t buf2[NTOR_ONIONSKIN_LEN] = {0}; or_circuit_t *circ1 = or_circuit_new(0, NULL); or_circuit_t *circ2 = or_circuit_new(0, NULL); - create_cell_t *onionskin = NULL, *create2_ptr; + create_cell_t *onionskin = NULL, *create1_ptr; create_cell_t *create1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create2 = tor_malloc_zero(sizeof(create_cell_t)); (void)arg; - create2_ptr = create2; /* remember, but do not free */ + create1_ptr = create1; /* remember, but do not free */ - create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, - TAP_ONIONSKIN_CHALLENGE_LEN, buf1); + create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, + NTOR_ONIONSKIN_LEN, buf1); create_cell_init(create2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, NTOR_ONIONSKIN_LEN, buf2); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(0,OP_EQ, onion_pending_add(circ1, create1)); create1 = NULL; - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(0,OP_EQ, onion_pending_add(circ2, create2)); create2 = NULL; - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); - tt_ptr_op(circ2,OP_EQ, onion_next_task(&onionskin)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); - tt_ptr_op(onionskin, OP_EQ, create2_ptr); + tt_ptr_op(circ1,OP_EQ, onion_next_task(&onionskin)); + tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + tt_ptr_op(onionskin, OP_EQ, create1_ptr); clear_pending_onions(); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); @@ -365,24 +219,19 @@ static void test_onion_queue_order(void *arg) { - uint8_t buf_tap[TAP_ONIONSKIN_CHALLENGE_LEN] = {0}; uint8_t buf_ntor[NTOR_ONIONSKIN_LEN] = {0}; uint8_t buf_ntor3[CELL_PAYLOAD_SIZE] = {0}; - or_circuit_t *circ_tap = or_circuit_new(0, NULL); or_circuit_t *circ_ntor = or_circuit_new(0, NULL); or_circuit_t *circ_ntor3 = or_circuit_new(0, NULL); create_cell_t *onionskin = NULL; - create_cell_t *create_tap1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create_ntor1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create_ntor2 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create_v3ntor1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create_v3ntor2 = tor_malloc_zero(sizeof(create_cell_t)); (void)arg; - create_cell_init(create_tap1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, - TAP_ONIONSKIN_CHALLENGE_LEN, buf_tap); create_cell_init(create_ntor1, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, NTOR_ONIONSKIN_LEN, buf_ntor); create_cell_init(create_ntor2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, @@ -393,78 +242,63 @@ NTOR_ONIONSKIN_LEN, buf_ntor3); /* sanity check queue init */ - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); - - /* Add tap first so we can ensure it comes out last */ - tt_int_op(0,OP_EQ, onion_pending_add(circ_tap, create_tap1)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); /* Now add interleaving ntor2 and ntor3, to ensure they share * the same queue and come out in this order */ tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor, create_ntor1)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor3, create_v3ntor1)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor, create_ntor2)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor3, create_v3ntor2)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(4,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(4,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); /* Now remove 5 tasks, ensuring order and queue sizes */ tt_ptr_op(circ_ntor, OP_EQ, onion_next_task(&onionskin)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); tt_ptr_op(onionskin, OP_EQ, create_ntor1); tt_ptr_op(circ_ntor3, OP_EQ, onion_next_task(&onionskin)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); tt_ptr_op(onionskin, OP_EQ, create_v3ntor1); tt_ptr_op(circ_ntor, OP_EQ, onion_next_task(&onionskin)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); tt_ptr_op(onionskin, OP_EQ, create_ntor2); tt_ptr_op(circ_ntor3, OP_EQ, onion_next_task(&onionskin)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); - tt_ptr_op(onionskin, OP_EQ, create_v3ntor2); - - tt_ptr_op(circ_tap, OP_EQ, onion_next_task(&onionskin)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); - tt_ptr_op(onionskin, OP_EQ, create_tap1); + tt_ptr_op(onionskin, OP_EQ, create_v3ntor2); clear_pending_onions(); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); done: - circuit_free_(TO_CIRCUIT(circ_tap)); circuit_free_(TO_CIRCUIT(circ_ntor)); circuit_free_(TO_CIRCUIT(circ_ntor3)); - tor_free(create_tap1); tor_free(create_ntor1); tor_free(create_ntor2); tor_free(create_v3ntor1); @@ -740,8 +574,6 @@ { #name, test_ ## name , TT_FORK, NULL, NULL } static struct testcase_t test_array[] = { - ENT(onion_handshake), - { "bad_onion_handshake", test_bad_onion_handshake, 0, NULL, NULL }, ENT(onion_queues), ENT(onion_queue_order), { "ntor_handshake", test_ntor_handshake, 0, NULL, NULL }, @@ -797,6 +629,7 @@ #endif { "crypto/pem/", pem_tests }, { "crypto/rng/", crypto_rng_tests }, + { "crypto/cgo/", crypto_cgo_tests }, { "dir/", dir_tests }, { "dir/auth/ports/", dirauth_port_tests }, { "dir/auth/process_descs/", process_descs_tests }, diff -Nru tor-0.4.8.16/src/test/test.h tor-0.4.9.6/src/test/test.h --- tor-0.4.8.16/src/test/test.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test.h 2026-03-25 14:30:34.000000000 +0000 @@ -122,6 +122,7 @@ extern struct testcase_t crypto_ope_tests[]; extern struct testcase_t crypto_openssl_tests[]; extern struct testcase_t crypto_rng_tests[]; +extern struct testcase_t crypto_cgo_tests[]; extern struct testcase_t crypto_tests[]; extern struct testcase_t dirauth_port_tests[]; extern struct testcase_t dir_handle_get_tests[]; diff -Nru tor-0.4.8.16/src/test/test_bridges.c tor-0.4.9.6/src/test/test_bridges.c --- tor-0.4.8.16/src/test/test_bridges.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_bridges.c 2026-03-25 14:30:34.000000000 +0000 @@ -253,7 +253,7 @@ { char digest[DIGEST_LEN]; bridge_info_t *bridge; - const char fingerprint[HEX_DIGEST_LEN] = + NONSTRING const char fingerprint[HEX_DIGEST_LEN] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t)); char ret_addr[16]; @@ -321,7 +321,7 @@ { char digest[DIGEST_LEN]; bridge_info_t *bridge; - const char fingerprint[HEX_DIGEST_LEN] = + NONSTRING const char fingerprint[HEX_DIGEST_LEN] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t)); uint16_t port = 11111; @@ -353,7 +353,7 @@ { char digest[DIGEST_LEN]; bridge_info_t *bridge; - const char fingerprint[HEX_DIGEST_LEN] = + NONSTRING const char fingerprint[HEX_DIGEST_LEN] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; tor_addr_t *addr = tor_malloc(sizeof(tor_addr_t)); uint16_t port = 4444; @@ -419,7 +419,7 @@ { char digest1[DIGEST_LEN]; bridge_info_t *bridge; - const char fingerprint[HEX_DIGEST_LEN] = + NONSTRING const char fingerprint[HEX_DIGEST_LEN] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; helper_add_bridges_to_bridgelist(arg); @@ -616,10 +616,10 @@ node_t node_with_digest; memset(&node_with_digest, 0, sizeof(node_with_digest)); - const char fingerprint[HEX_DIGEST_LEN] = + NONSTRING const char fingerprint[HEX_DIGEST_LEN] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - const char fingerprint2[HEX_DIGEST_LEN] = + NONSTRING const char fingerprint2[HEX_DIGEST_LEN] = "ffffffffffffffffffffffffffffffffffffffff"; base16_decode(node_with_digest.identity, DIGEST_LEN, diff -Nru tor-0.4.8.16/src/test/test_cell_formats.c tor-0.4.9.6/src/test/test_cell_formats.c --- tor-0.4.8.16/src/test/test_cell_formats.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_cell_formats.c 2026-03-25 14:30:34.000000000 +0000 @@ -14,13 +14,14 @@ #include "app/config/config.h" #include "lib/crypt_ops/crypto_rand.h" #include "core/or/onion.h" -#include "core/crypto/onion_tap.h" #include "core/crypto/onion_fast.h" #include "core/crypto/onion_ntor.h" #include "core/or/relay.h" +#include "core/or/relay_msg.h" #include "core/or/cell_st.h" #include "core/or/cell_queue_st.h" +#include "core/or/relay_msg_st.h" #include "core/or/var_cell_st.h" #include "test/test.h" @@ -32,12 +33,12 @@ test_cfmt_relay_header(void *arg) { relay_header_t rh; - const uint8_t hdr_1[RELAY_HEADER_SIZE] = + NONSTRING const uint8_t hdr_1[RELAY_HEADER_SIZE_V0] = "\x03" "\x00\x00" "\x21\x22" "ABCD" "\x01\x03"; - uint8_t hdr_out[RELAY_HEADER_SIZE]; + uint8_t hdr_out[RELAY_HEADER_SIZE_V0]; (void)arg; - tt_int_op(sizeof(hdr_1), OP_EQ, RELAY_HEADER_SIZE); + tt_int_op(sizeof(hdr_1), OP_EQ, RELAY_HEADER_SIZE_V0); relay_header_unpack(&rh, hdr_1); tt_int_op(rh.command, OP_EQ, 3); tt_int_op(rh.recognized, OP_EQ, 0); @@ -46,42 +47,35 @@ tt_int_op(rh.length, OP_EQ, 0x103); relay_header_pack(hdr_out, &rh); - tt_mem_op(hdr_out, OP_EQ, hdr_1, RELAY_HEADER_SIZE); + tt_mem_op(hdr_out, OP_EQ, hdr_1, RELAY_HEADER_SIZE_V0); done: ; } static void -make_relay_cell(cell_t *out, uint8_t command, - const void *body, size_t bodylen) +make_relay_msg(relay_msg_t *out, uint8_t command, + const void *body, size_t bodylen) { - relay_header_t rh; - - memset(&rh, 0, sizeof(rh)); - rh.stream_id = 5; - rh.command = command; - rh.length = bodylen; - - out->command = CELL_RELAY; - out->circ_id = 10; - relay_header_pack(out->payload, &rh); - - memcpy(out->payload + RELAY_HEADER_SIZE, body, bodylen); + memset(out, 0, sizeof(*out)); + out->command = command; + out->body = (uint8_t *)body; + out->length = bodylen; + out->stream_id = 5; } static void test_cfmt_begin_cells(void *arg) { - cell_t cell; + relay_msg_t msg; begin_cell_t bcell; uint8_t end_reason; (void)arg; /* Try begindir. */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN_DIR, "", 0); - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN_DIR, "", 0); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); tt_ptr_op(NULL, OP_EQ, bcell.address); tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(0, OP_EQ, bcell.port); @@ -90,8 +84,8 @@ /* A Begindir with extra stuff. */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN_DIR, "12345", 5); - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN_DIR, "12345", 5); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); tt_ptr_op(NULL, OP_EQ, bcell.address); tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(0, OP_EQ, bcell.port); @@ -100,8 +94,8 @@ /* A short but valid begin cell */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:9", 6); - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b:9", 6); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); tt_str_op("a.b", OP_EQ, bcell.address); tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(9, OP_EQ, bcell.port); @@ -112,21 +106,21 @@ /* A significantly loner begin cell */ memset(&bcell, 0x7f, sizeof(bcell)); { - const char c[] = "here-is-a-nice-long.hostname.com:65535"; - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, strlen(c)+1); - } - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + const char c[] = "here-is-a-nice-long.hostname.com:65535"; + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, c, strlen(c)+1); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); tt_str_op("here-is-a-nice-long.hostname.com", OP_EQ, bcell.address); tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(65535, OP_EQ, bcell.port); tt_int_op(5, OP_EQ, bcell.stream_id); tt_int_op(0, OP_EQ, bcell.is_begindir); tor_free(bcell.address); + } /* An IPv4 begin cell. */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "18.9.22.169:80", 15); - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "18.9.22.169:80", 15); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); tt_str_op("18.9.22.169", OP_EQ, bcell.address); tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(80, OP_EQ, bcell.port); @@ -136,9 +130,9 @@ /* An IPv6 begin cell. Let's make sure we handle colons*/ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "[2620::6b0:b:1a1a:0:26e5:480e]:80", 34); - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); tt_str_op("[2620::6b0:b:1a1a:0:26e5:480e]", OP_EQ, bcell.address); tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(80, OP_EQ, bcell.port); @@ -150,88 +144,85 @@ memset(&bcell, 0x7f, sizeof(bcell)); { const char c[] = "another.example.com:80\x00\x01\x02"; - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); + tt_str_op("another.example.com", OP_EQ, bcell.address); + tt_int_op(0, OP_EQ, bcell.flags); + tt_int_op(80, OP_EQ, bcell.port); + tt_int_op(5, OP_EQ, bcell.stream_id); + tt_int_op(0, OP_EQ, bcell.is_begindir); + tor_free(bcell.address); } - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); - tt_str_op("another.example.com", OP_EQ, bcell.address); - tt_int_op(0, OP_EQ, bcell.flags); - tt_int_op(80, OP_EQ, bcell.port); - tt_int_op(5, OP_EQ, bcell.stream_id); - tt_int_op(0, OP_EQ, bcell.is_begindir); - tor_free(bcell.address); /* a begin cell with flags. */ memset(&bcell, 0x7f, sizeof(bcell)); { const char c[] = "another.example.com:443\x00\x01\x02\x03\x04"; - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); + tt_str_op("another.example.com", OP_EQ, bcell.address); + tt_int_op(0x1020304, OP_EQ, bcell.flags); + tt_int_op(443, OP_EQ, bcell.port); + tt_int_op(5, OP_EQ, bcell.stream_id); + tt_int_op(0, OP_EQ, bcell.is_begindir); + tor_free(bcell.address); } - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); - tt_str_op("another.example.com", OP_EQ, bcell.address); - tt_int_op(0x1020304, OP_EQ, bcell.flags); - tt_int_op(443, OP_EQ, bcell.port); - tt_int_op(5, OP_EQ, bcell.stream_id); - tt_int_op(0, OP_EQ, bcell.is_begindir); - tor_free(bcell.address); /* a begin cell with flags and even more cruft after that. */ memset(&bcell, 0x7f, sizeof(bcell)); { const char c[] = "a-further.example.com:22\x00\xee\xaa\x00\xffHi mom"; - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); + tt_str_op("a-further.example.com", OP_EQ, bcell.address); + tt_int_op(0xeeaa00ff, OP_EQ, bcell.flags); + tt_int_op(22, OP_EQ, bcell.port); + tt_int_op(5, OP_EQ, bcell.stream_id); + tt_int_op(0, OP_EQ, bcell.is_begindir); + tor_free(bcell.address); } - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); - tt_str_op("a-further.example.com", OP_EQ, bcell.address); - tt_int_op(0xeeaa00ff, OP_EQ, bcell.flags); - tt_int_op(22, OP_EQ, bcell.port); - tt_int_op(5, OP_EQ, bcell.stream_id); - tt_int_op(0, OP_EQ, bcell.is_begindir); - tor_free(bcell.address); +#if 0 + // Note: This is now checked at when we decode the relay message. /* bad begin cell: impossible length. */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:80", 7); - cell.payload[9] = 0x01; /* Set length to 510 */ - cell.payload[10] = 0xfe; - { - relay_header_t rh; - relay_header_unpack(&rh, cell.payload); - tt_int_op(rh.length, OP_EQ, 510); - } - tt_int_op(-2, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b:80", 7); + msg.length = 510; + tt_int_op(-2, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); +#endif /* Bad begin cell: no body. */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "", 0); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "", 0); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); /* bad begin cell: no body. */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "", 0); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "", 0); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); /* bad begin cell: no colon */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b", 4); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b", 4); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); /* bad begin cell: no ports */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:", 5); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b:", 5); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); /* bad begin cell: bad port */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:xyz", 8); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b:xyz", 8); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:100000", 11); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b:100000", 11); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); /* bad begin cell: no nul */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:80", 6); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b:80", 6); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); done: tor_free(bcell.address); @@ -240,144 +231,129 @@ static void test_cfmt_connected_cells(void *arg) { - relay_header_t rh; - cell_t cell; tor_addr_t addr; int ttl, r; char *mem_op_hex_tmp = NULL; + relay_msg_t msg; + uint8_t buf[512]; (void)arg; /* Let's try an oldschool one with nothing in it. */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "", 0); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "", 0); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_UNSPEC); tt_int_op(ttl, OP_EQ, -1); /* A slightly less oldschool one: only an IPv4 address */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "\x20\x30\x40\x50", 4); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x20\x30\x40\x50", 4); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET); tt_str_op(fmt_addr(&addr), OP_EQ, "32.48.64.80"); tt_int_op(ttl, OP_EQ, -1); /* Bogus but understandable: truncated TTL */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "\x11\x12\x13\x14\x15", 5); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x11\x12\x13\x14\x15", 5); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET); tt_str_op(fmt_addr(&addr), OP_EQ, "17.18.19.20"); tt_int_op(ttl, OP_EQ, -1); /* Regular IPv4 one: address and TTL */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x02\x03\x04\x05\x00\x00\x0e\x10", 8); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET); tt_str_op(fmt_addr(&addr), OP_EQ, "2.3.4.5"); tt_int_op(ttl, OP_EQ, 3600); /* IPv4 with too-big TTL */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x02\x03\x04\x05\xf0\x00\x00\x00", 8); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET); tt_str_op(fmt_addr(&addr), OP_EQ, "2.3.4.5"); tt_int_op(ttl, OP_EQ, -1); /* IPv6 (ttl is mandatory) */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x00\x00\x00\x00\x06" "\x26\x07\xf8\xb0\x40\x0c\x0c\x02" "\x00\x00\x00\x00\x00\x00\x00\x68" "\x00\x00\x02\x58", 25); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET6); tt_str_op(fmt_addr(&addr), OP_EQ, "2607:f8b0:400c:c02::68"); tt_int_op(ttl, OP_EQ, 600); /* IPv6 (ttl too big) */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x00\x00\x00\x00\x06" "\x26\x07\xf8\xb0\x40\x0c\x0c\x02" "\x00\x00\x00\x00\x00\x00\x00\x68" "\x90\x00\x02\x58", 25); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET6); tt_str_op(fmt_addr(&addr), OP_EQ, "2607:f8b0:400c:c02::68"); tt_int_op(ttl, OP_EQ, -1); /* Bogus size: 3. */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x00\x01\x02", 3); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, -1); /* Bogus family: 7. */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x00\x00\x00\x00\x07" "\x26\x07\xf8\xb0\x40\x0c\x0c\x02" "\x00\x00\x00\x00\x00\x00\x00\x68" "\x90\x00\x02\x58", 25); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, -1); /* Truncated IPv6. */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x00\x00\x00\x00\x06" "\x26\x07\xf8\xb0\x40\x0c\x0c\x02" "\x00\x00\x00\x00\x00\x00\x00\x68" "\x00\x00\x02", 24); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, -1); /* Now make sure we can generate connected cells correctly. */ /* Try an IPv4 address */ - memset(&rh, 0, sizeof(rh)); - memset(&cell, 0, sizeof(cell)); tor_addr_parse(&addr, "30.40.50.60"); - rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE, - &addr, 1024); - tt_int_op(rh.length, OP_EQ, 8); - test_memeq_hex(cell.payload+RELAY_HEADER_SIZE, "1e28323c" "00000400"); + msg.body = buf; + msg.length = connected_cell_format_payload(buf, &addr, 1024); + tt_int_op(msg.length, OP_EQ, 8); + test_memeq_hex(msg.body, "1e28323c" "00000400"); /* Try parsing it. */ tor_addr_make_unspec(&addr); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET); tt_str_op(fmt_addr(&addr), OP_EQ, "30.40.50.60"); tt_int_op(ttl, OP_EQ, 1024); /* Try an IPv6 address */ - memset(&rh, 0, sizeof(rh)); - memset(&cell, 0, sizeof(cell)); tor_addr_parse(&addr, "2620::6b0:b:1a1a:0:26e5:480e"); - rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE, - &addr, 3600); - tt_int_op(rh.length, OP_EQ, 25); - test_memeq_hex(cell.payload + RELAY_HEADER_SIZE, + msg.length = connected_cell_format_payload(buf, &addr, 3600); + tt_int_op(msg.length, OP_EQ, 25); + test_memeq_hex(msg.body, "00000000" "06" "2620000006b0000b1a1a000026e5480e" "00000e10"); /* Try parsing it. */ tor_addr_make_unspec(&addr); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET6); tt_str_op(fmt_addr(&addr), OP_EQ, "2620:0:6b0:b:1a1a:0:26e5:480e"); @@ -399,21 +375,6 @@ /* === Let's try parsing some good cells! */ - /* A valid create cell. */ - memset(&cell, 0, sizeof(cell)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN); - cell.command = CELL_CREATE; - memcpy(cell.payload, b, TAP_ONIONSKIN_CHALLENGE_LEN); - tt_int_op(0, OP_EQ, create_cell_parse(&cc, &cell)); - tt_int_op(CELL_CREATE, OP_EQ, cc.cell_type); - tt_int_op(ONION_HANDSHAKE_TYPE_TAP, OP_EQ, cc.handshake_type); - tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, OP_EQ, cc.handshake_len); - tt_mem_op(cc.onionskin,OP_EQ, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10); - tt_int_op(0, OP_EQ, create_cell_format(&cell2, &cc)); - tt_int_op(cell.command, OP_EQ, cell2.command); - tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE); - /* A valid create_fast cell. */ memset(&cell, 0, sizeof(cell)); memset(b, 0, sizeof(b)); @@ -429,22 +390,6 @@ tt_int_op(cell.command, OP_EQ, cell2.command); tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE); - /* A valid create2 cell with a TAP payload */ - memset(&cell, 0, sizeof(cell)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN); - cell.command = CELL_CREATE2; - memcpy(cell.payload, "\x00\x00\x00\xBA", 4); /* TAP, 186 bytes long */ - memcpy(cell.payload+4, b, TAP_ONIONSKIN_CHALLENGE_LEN); - tt_int_op(0, OP_EQ, create_cell_parse(&cc, &cell)); - tt_int_op(CELL_CREATE2, OP_EQ, cc.cell_type); - tt_int_op(ONION_HANDSHAKE_TYPE_TAP, OP_EQ, cc.handshake_type); - tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, OP_EQ, cc.handshake_len); - tt_mem_op(cc.onionskin,OP_EQ, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10); - tt_int_op(0, OP_EQ, create_cell_format(&cell2, &cc)); - tt_int_op(cell.command, OP_EQ, cell2.command); - tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE); - /* A valid create2 cell with an ntor payload */ memset(&cell, 0, sizeof(cell)); memset(b, 0, sizeof(b)); @@ -461,22 +406,6 @@ tt_int_op(cell.command, OP_EQ, cell2.command); tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE); - /* A valid create cell with an ntor payload, in legacy format. */ - memset(&cell, 0, sizeof(cell)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, NTOR_ONIONSKIN_LEN); - cell.command = CELL_CREATE; - memcpy(cell.payload, "ntorNTORntorNTOR", 16); - memcpy(cell.payload+16, b, NTOR_ONIONSKIN_LEN); - tt_int_op(0, OP_EQ, create_cell_parse(&cc, &cell)); - tt_int_op(CELL_CREATE, OP_EQ, cc.cell_type); - tt_int_op(ONION_HANDSHAKE_TYPE_NTOR, OP_EQ, cc.handshake_type); - tt_int_op(NTOR_ONIONSKIN_LEN, OP_EQ, cc.handshake_len); - tt_mem_op(cc.onionskin,OP_EQ, b, NTOR_ONIONSKIN_LEN + 10); - tt_int_op(0, OP_EQ, create_cell_format(&cell2, &cc)); - tt_int_op(cell.command, OP_EQ, cell2.command); - tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE); - /* == Okay, now let's try to parse some impossible stuff. */ /* It has to be some kind of a create cell! */ @@ -517,20 +446,6 @@ (void)arg; - /* A good CREATED cell */ - memset(&cell, 0, sizeof(cell)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, TAP_ONIONSKIN_REPLY_LEN); - cell.command = CELL_CREATED; - memcpy(cell.payload, b, TAP_ONIONSKIN_REPLY_LEN); - tt_int_op(0, OP_EQ, created_cell_parse(&cc, &cell)); - tt_int_op(CELL_CREATED, OP_EQ, cc.cell_type); - tt_int_op(TAP_ONIONSKIN_REPLY_LEN, OP_EQ, cc.handshake_len); - tt_mem_op(cc.reply,OP_EQ, b, TAP_ONIONSKIN_REPLY_LEN + 10); - tt_int_op(0, OP_EQ, created_cell_format(&cell2, &cc)); - tt_int_op(cell.command, OP_EQ, cell2.command); - tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE); - /* A good CREATED_FAST cell */ memset(&cell, 0, sizeof(cell)); memset(b, 0, sizeof(b)); @@ -580,11 +495,11 @@ memset(b, 0, sizeof(b)); crypto_rand((char*)b, 496); cell.command = CELL_CREATED2; - memcpy(cell.payload, "\x01\xF1", 2); + memcpy(cell.payload, "\x02\xFF", 2); tt_int_op(-1, OP_EQ, created_cell_parse(&cc, &cell)); /* Unformattable CREATED2 cell: too long! */ - cc.handshake_len = 497; + cc.handshake_len = 508; tt_int_op(-1, OP_EQ, created_cell_format(&cell2, &cc)); done: @@ -606,54 +521,6 @@ (void) arg; - /* Let's start with a simple EXTEND cell. */ - memset(p, 0, sizeof(p)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN); - memcpy(p, "\x12\xf4\x00\x01\x01\x02", 6); /* 18 244 0 1 : 258 */ - memcpy(p+6,b,TAP_ONIONSKIN_CHALLENGE_LEN); - memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, "electroencephalogram", 20); - tt_int_op(0, OP_EQ, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND, - p, 26+TAP_ONIONSKIN_CHALLENGE_LEN)); - tt_int_op(RELAY_COMMAND_EXTEND, OP_EQ, ec.cell_type); - tt_str_op("18.244.0.1", OP_EQ, fmt_addr(&ec.orport_ipv4.addr)); - tt_int_op(258, OP_EQ, ec.orport_ipv4.port); - tt_int_op(AF_UNSPEC, OP_EQ, tor_addr_family(&ec.orport_ipv6.addr)); - tt_mem_op(ec.node_id,OP_EQ, "electroencephalogram", 20); - tt_int_op(cc->cell_type, OP_EQ, CELL_CREATE); - tt_int_op(cc->handshake_type, OP_EQ, ONION_HANDSHAKE_TYPE_TAP); - tt_int_op(cc->handshake_len, OP_EQ, TAP_ONIONSKIN_CHALLENGE_LEN); - tt_mem_op(cc->onionskin,OP_EQ, b, TAP_ONIONSKIN_CHALLENGE_LEN+20); - tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec)); - tt_int_op(p2_cmd, OP_EQ, RELAY_COMMAND_EXTEND); - tt_int_op(p2_len, OP_EQ, 26+TAP_ONIONSKIN_CHALLENGE_LEN); - tt_mem_op(p2,OP_EQ, p, RELAY_PAYLOAD_SIZE); - - /* Let's do an ntor stuffed in a legacy EXTEND cell */ - memset(p, 0, sizeof(p)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, NTOR_ONIONSKIN_LEN); - memcpy(p, "\x12\xf4\x00\x01\x01\x02", 6); /* 18 244 0 1 : 258 */ - memcpy(p+6,"ntorNTORntorNTOR", 16); - memcpy(p+22, b, NTOR_ONIONSKIN_LEN); - memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, "electroencephalogram", 20); - tt_int_op(0, OP_EQ, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND, - p, 26+TAP_ONIONSKIN_CHALLENGE_LEN)); - tt_int_op(RELAY_COMMAND_EXTEND, OP_EQ, ec.cell_type); - tt_str_op("18.244.0.1", OP_EQ, fmt_addr(&ec.orport_ipv4.addr)); - tt_int_op(258, OP_EQ, ec.orport_ipv4.port); - tt_int_op(AF_UNSPEC, OP_EQ, tor_addr_family(&ec.orport_ipv6.addr)); - tt_mem_op(ec.node_id,OP_EQ, "electroencephalogram", 20); - tt_int_op(cc->cell_type, OP_EQ, CELL_CREATE2); - tt_int_op(cc->handshake_type, OP_EQ, ONION_HANDSHAKE_TYPE_NTOR); - tt_int_op(cc->handshake_len, OP_EQ, NTOR_ONIONSKIN_LEN); - tt_mem_op(cc->onionskin,OP_EQ, b, NTOR_ONIONSKIN_LEN+20); - tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec)); - tt_int_op(p2_cmd, OP_EQ, RELAY_COMMAND_EXTEND); - tt_int_op(p2_len, OP_EQ, 26+TAP_ONIONSKIN_CHALLENGE_LEN); - tt_mem_op(p2,OP_EQ, p, RELAY_PAYLOAD_SIZE); - tt_int_op(0, OP_EQ, create_cell_format_relayed(&cell, cc)); - /* Now let's do a minimal ntor EXTEND2 cell. */ memset(&ec, 0xff, sizeof(ec)); memset(p, 0, sizeof(p)); @@ -896,23 +763,6 @@ (void) arg; - /* Try a regular EXTENDED cell. */ - memset(&ec, 0xff, sizeof(ec)); - memset(p, 0, sizeof(p)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, TAP_ONIONSKIN_REPLY_LEN); - memcpy(p,b,TAP_ONIONSKIN_REPLY_LEN); - tt_int_op(0, OP_EQ, extended_cell_parse(&ec, RELAY_COMMAND_EXTENDED, p, - TAP_ONIONSKIN_REPLY_LEN)); - tt_int_op(RELAY_COMMAND_EXTENDED, OP_EQ, ec.cell_type); - tt_int_op(cc->cell_type, OP_EQ, CELL_CREATED); - tt_int_op(cc->handshake_len, OP_EQ, TAP_ONIONSKIN_REPLY_LEN); - tt_mem_op(cc->reply,OP_EQ, b, TAP_ONIONSKIN_REPLY_LEN); - tt_int_op(0, OP_EQ, extended_cell_format(&p2_cmd, &p2_len, p2, &ec)); - tt_int_op(RELAY_COMMAND_EXTENDED, OP_EQ, p2_cmd); - tt_int_op(TAP_ONIONSKIN_REPLY_LEN, OP_EQ, p2_len); - tt_mem_op(p2,OP_EQ, p, sizeof(p2)); - /* Try an EXTENDED2 cell */ memset(&ec, 0xff, sizeof(ec)); memset(p, 0, sizeof(p)); @@ -950,15 +800,15 @@ test_cfmt_resolved_cells(void *arg) { smartlist_t *addrs = smartlist_new(); - relay_header_t rh; - cell_t cell; int r, errcode; address_ttl_t *a; + relay_msg_t msg; + uint8_t buf[500]; (void)arg; #define CLEAR_CELL() do { \ - memset(&cell, 0, sizeof(cell)); \ - memset(&rh, 0, sizeof(rh)); \ + memset(&msg, 0, sizeof(msg)); \ + memset(&buf, 0, sizeof(buf)); \ } while (0) #define CLEAR_ADDRS() do { \ SMARTLIST_FOREACH(addrs, address_ttl_t *, aa_, \ @@ -967,9 +817,10 @@ } while (0) #define SET_CELL(s) do { \ CLEAR_CELL(); \ - memcpy(cell.payload + RELAY_HEADER_SIZE, (s), sizeof((s))-1); \ - rh.length = sizeof((s))-1; \ - rh.command = RELAY_COMMAND_RESOLVED; \ + memcpy(buf, (s), sizeof((s))-1); \ + msg.length = sizeof((s))-1; \ + msg.body = buf; \ + msg.command = RELAY_COMMAND_RESOLVED; \ errcode = -1; \ } while (0) @@ -982,7 +833,7 @@ /* Let's try an empty cell */ SET_CELL(""); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 0); @@ -990,8 +841,8 @@ /* Cell with one ipv4 addr */ SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00"); - tt_int_op(rh.length, OP_EQ, 10); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 10); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 1); @@ -1006,8 +857,8 @@ "\x20\x02\x90\x90\x00\x00\x00\x00" "\x00\x00\x00\x00\xf0\xf0\xab\xcd" "\x02\00\x00\x01"); - tt_int_op(rh.length, OP_EQ, 22); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 22); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 1); @@ -1021,8 +872,8 @@ SET_CELL("\x00\x11" "motherbrain.zebes" "\x00\00\x00\x00"); - tt_int_op(rh.length, OP_EQ, 23); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 23); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 1); @@ -1042,8 +893,8 @@ SET_CELL("\x00\xff" LONG_NAME "\x00\01\x00\x00"); - tt_int_op(rh.length, OP_EQ, 261); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 261); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 1); @@ -1057,8 +908,8 @@ SET_CELL("\xf0\x2b" "I'm sorry, Dave. I'm afraid I can't do that" "\x00\x11\x22\x33"); - tt_int_op(rh.length, OP_EQ, 49); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 49); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, RESOLVED_TYPE_ERROR_TRANSIENT); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 0); @@ -1067,8 +918,8 @@ SET_CELL("\xf1\x40" "This hostname is too important for me to allow you to resolve it" "\x00\x00\x00\x00"); - tt_int_op(rh.length, OP_EQ, 70); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 70); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, RESOLVED_TYPE_ERROR); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 0); @@ -1078,8 +929,8 @@ SET_CELL("\xee\x16" "fault in the AE35 unit" "\x09\x09\x01\x01"); - tt_int_op(rh.length, OP_EQ, 28); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 28); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 0); @@ -1106,7 +957,7 @@ "motherbrain.zebes" "\x00\00\x00\x00" ); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); /* no error reported; we got answers */ tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 3); @@ -1138,7 +989,7 @@ "\x20\x02\x90\x01\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\xfa\xca\xde" "\x00\00\x00\x03"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 5); @@ -1178,8 +1029,8 @@ "\x00\xe7" LONG_NAME2 "\x00\01\x00\x00"); - tt_int_op(rh.length, OP_EQ, RELAY_PAYLOAD_SIZE); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, RELAY_PAYLOAD_SIZE); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 2); @@ -1193,68 +1044,71 @@ /* Invalid length on an IPv4 */ SET_CELL("\x04\x03zzz1234"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00" "\x04\x05zzzzz1234"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); /* Invalid length on an IPv6 */ SET_CELL("\x06\x03zzz1234"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00" "\x06\x17wwwwwwwwwwwwwwwww1234"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00" "\x06\x10xxxx"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); /* Empty hostname */ SET_CELL("\x00\x00xxxx"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); +#if 0 + //No longer possible with relay message encoding. /* rh.length out of range */ CLEAR_CELL(); rh.length = 499; - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); +#endif /* Item length extends beyond rh.length */ CLEAR_CELL(); SET_CELL("\x00\xff" LONG_NAME "\x00\01\x00\x00"); - rh.length -= 1; - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + msg.length -= 1; + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); - rh.length -= 5; - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + msg.length -= 5; + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00"); - rh.length -= 1; - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + msg.length -= 1; + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); @@ -1262,19 +1116,19 @@ "\x20\x02\x90\x01\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\xfa\xca\xde" "\x00\00\x00\x03"); - rh.length -= 1; - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + msg.length -= 1; + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); /* Truncated item after first character */ SET_CELL("\x04"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); SET_CELL("\xee"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); @@ -1327,6 +1181,419 @@ tor_free(chan); } +static void +test_cfmt_relay_msg_encoding_simple(void *arg) +{ + (void)arg; + relay_msg_t *msg1 = NULL; + cell_t cell; + char *mem_op_hex_tmp = NULL; + int r; + uint8_t body[100]; + + /* Simple message: Data, fits easily in cell. */ + msg1 = tor_malloc_zero(sizeof(relay_msg_t)); + msg1->command = RELAY_COMMAND_DATA; + msg1->stream_id = 0x250; + msg1->length = 11; + msg1->body = body; + strlcpy((char*)body, "hello world", sizeof(body)); + + r = relay_msg_encode_cell(RELAY_CELL_FORMAT_V0, msg1, &cell); + tt_int_op(r, OP_EQ, 0); + tt_int_op(cell.command, OP_EQ, CELL_RELAY); + tt_int_op(cell.circ_id, OP_EQ, 0); + // command, recognized, streamid, digest, len, payload, zero-padding. + test_memeq_hex(cell.payload, + "02" "0000" "0250" "00000000" "000B" + "68656c6c6f20776f726c64" "00000000"); + // random padding + size_t used = RELAY_HEADER_SIZE_V0 + 11 + 4; + tt_assert(!fast_mem_is_zero((char*)cell.payload + used, + CELL_PAYLOAD_SIZE - used)); + + r = relay_msg_encode_cell(RELAY_CELL_FORMAT_V1, msg1, &cell); + tt_int_op(r, OP_EQ, 0); + tt_int_op(cell.command, OP_EQ, CELL_RELAY); + tt_int_op(cell.circ_id, OP_EQ, 0); + // tag, command, len, optional streamid, payload, zero-padding + test_memeq_hex(cell.payload, + "00000000000000000000000000000000" + "02" "000B" "0250" + "68656c6c6f20776f726c64" "00000000"); + // random padding. + used = RELAY_HEADER_SIZE_V1_WITH_STREAM_ID + 11 + 4; + tt_assert(!fast_mem_is_zero((char*)cell.payload + used, + CELL_PAYLOAD_SIZE - used)); + + /* Message without stream ID: SENDME, fits easily in cell. */ + relay_msg_clear(msg1); + msg1->command = RELAY_COMMAND_SENDME; + msg1->stream_id = 0; + msg1->length = 20; + msg1->body = body; + strlcpy((char *)body, "hello i am a tag....", sizeof(body)); + + r = relay_msg_encode_cell(RELAY_CELL_FORMAT_V0, msg1, &cell); + tt_int_op(r, OP_EQ, 0); + tt_int_op(cell.command, OP_EQ, CELL_RELAY); + tt_int_op(cell.circ_id, OP_EQ, 0); + // command, recognized, streamid, digest, len, payload, zero-padding. + test_memeq_hex(cell.payload, + "05" "0000" "0000" "00000000" "0014" + "68656c6c6f206920616d2061207461672e2e2e2e" "00000000"); + // random padding + used = RELAY_HEADER_SIZE_V0 + 20 + 4; + tt_assert(!fast_mem_is_zero((char*)cell.payload + used, + CELL_PAYLOAD_SIZE - used)); + + r = relay_msg_encode_cell(RELAY_CELL_FORMAT_V1, msg1, &cell); + tt_int_op(r, OP_EQ, 0); + tt_int_op(cell.command, OP_EQ, CELL_RELAY); + tt_int_op(cell.circ_id, OP_EQ, 0); + // tag, command, len, optional streamid, payload, zero-padding + test_memeq_hex(cell.payload, + "00000000000000000000000000000000" + "05" "0014" + "68656c6c6f206920616d2061207461672e2e2e2e" "00000000"); + // random padding. + used = RELAY_HEADER_SIZE_V1_NO_STREAM_ID + 20 + 4; + tt_assert(!fast_mem_is_zero((char*)cell.payload + used, + CELL_PAYLOAD_SIZE - used)); + + done: + relay_msg_free(msg1); + tor_free(mem_op_hex_tmp); +} + +/** Helper for test_cfmt_relay_cell_padding. + * Requires that that the body of 'msg' ends with 'pre_padding_byte', + * and that when encoded, the zero-padding (if any) will appear at + * offset 'zeros_begin_at' in the message. + */ +static void +msg_encoder_padding_test(const relay_msg_t *msg, + relay_cell_fmt_t fmt, + uint8_t pre_padding_byte, + size_t zeros_begin_at) +{ + cell_t cell; + int n = 16, i; + /* We set this to 0 as soon as we find that the first byte of + * random padding has been set. */ + bool padded_first = false; + /* We set this to true as soon as we find that the last byte of + * random padding has been set */ + bool padded_last = false; + + tt_int_op(zeros_begin_at, OP_LE, CELL_PAYLOAD_SIZE); + + size_t expect_n_zeros = MIN(4, CELL_PAYLOAD_SIZE - zeros_begin_at); + ssize_t first_random_at = -1; + if (CELL_PAYLOAD_SIZE - zeros_begin_at > 4) { + first_random_at = CELL_PAYLOAD_SIZE - zeros_begin_at + 4; + } + + for (i = 0; i < n; ++i) { + memset(&cell, 0, sizeof(cell)); + tt_int_op(0, OP_EQ, + relay_msg_encode_cell(fmt, msg, &cell)); + + const uint8_t *body = cell.payload; + tt_int_op(body[zeros_begin_at - 1], OP_EQ, pre_padding_byte); + + if (expect_n_zeros) { + tt_assert(fast_mem_is_zero((char*)body + zeros_begin_at, + expect_n_zeros)); + } + if (first_random_at >= 0) { + if (body[first_random_at]) + padded_first = true; + if (body[CELL_PAYLOAD_SIZE-1]) + padded_last = true; + } + } + + if (first_random_at >= 0) { + tt_assert(padded_first); + tt_assert(padded_last); + } + + done: + ; +} + +static void +test_cfmt_relay_cell_padding(void *arg) +{ + (void)arg; + relay_msg_t *msg1 = NULL; + uint8_t buf[500]; // Longer than it needs to be. + memset(buf, 0xff, sizeof(buf)); + + /* Simple message; we'll adjust the length and encode it. */ + msg1 = tor_malloc_zero(sizeof(relay_msg_t)); + msg1->command = RELAY_COMMAND_DATA; + msg1->stream_id = 0x250; + msg1->body = buf; + + // Empty message + msg1->length = 0; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V0, 0x00, + RELAY_HEADER_SIZE_V0); + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V1, 0x50, + RELAY_HEADER_SIZE_V1_WITH_STREAM_ID); + + // Short message + msg1->length = 10; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V0, 0xff, + RELAY_HEADER_SIZE_V0 + 10); + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V1, 0xff, + RELAY_HEADER_SIZE_V1_WITH_STREAM_ID + 10); + + // Message where zeros extend exactly up to the end of the cell. + msg1->length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE_V0 - 4; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V0, 0xff, + RELAY_HEADER_SIZE_V0 + msg1->length); + msg1->length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE_V1_WITH_STREAM_ID - 4; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V1, 0xff, + RELAY_HEADER_SIZE_V1_WITH_STREAM_ID + msg1->length); + + // Message where zeros would intersect with the end of the cell. + msg1->length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE_V0 - 3; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V0, 0xff, + RELAY_HEADER_SIZE_V0 + msg1->length); + msg1->length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE_V1_WITH_STREAM_ID - 3; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V1, 0xff, + RELAY_HEADER_SIZE_V1_WITH_STREAM_ID + msg1->length); + + // Message with no room for zeros + msg1->length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE_V0; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V0, 0xff, + RELAY_HEADER_SIZE_V0 + msg1->length); + msg1->length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE_V1_WITH_STREAM_ID; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V1, 0xff, + RELAY_HEADER_SIZE_V1_WITH_STREAM_ID + msg1->length); + + /////////////// + // V1 cases with no stream ID. + msg1->stream_id = 0; + msg1->command = RELAY_COMMAND_EXTENDED; + + msg1->length = 0; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V1, 0x00, + RELAY_HEADER_SIZE_V1_NO_STREAM_ID); + msg1->length = 10; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V1, 0xff, + RELAY_HEADER_SIZE_V1_NO_STREAM_ID + 10); + msg1->length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE_V1_NO_STREAM_ID - 4; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V1, 0xff, + RELAY_HEADER_SIZE_V1_NO_STREAM_ID + msg1->length); + msg1->length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE_V1_NO_STREAM_ID - 3; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V1, 0xff, + RELAY_HEADER_SIZE_V1_NO_STREAM_ID + msg1->length); + msg1->length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE_V1_NO_STREAM_ID; + msg_encoder_padding_test(msg1, RELAY_CELL_FORMAT_V1, 0xff, + RELAY_HEADER_SIZE_V1_NO_STREAM_ID + msg1->length); + + relay_msg_free(msg1); +} + +static void +test_cfmt_relay_msg_encoding_error(void *arg) +{ + (void)arg; +#ifdef ALL_BUGS_ARE_FATAL + // This test triggers many nonfatal assertions. + tt_skip(); + done: + ; +#else + relay_msg_t *msg1 = NULL; + int r; + cell_t cell; + uint8_t buf[500]; // Longer than it needs to be. + memset(buf, 0xff, sizeof(buf)); + + msg1 = tor_malloc_zero(sizeof(relay_msg_t)); + msg1->command = RELAY_COMMAND_DATA; + msg1->stream_id = 0x250; + msg1->body = buf; + + tor_capture_bugs_(5); + // Too long for v0. + msg1->length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE_V0 + 1; + r = relay_msg_encode_cell(RELAY_CELL_FORMAT_V0, msg1, &cell); + tt_int_op(r, OP_EQ, -1); + + // Too long for v1, with stream ID. + msg1->length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE_V1_WITH_STREAM_ID + 1; + r = relay_msg_encode_cell(RELAY_CELL_FORMAT_V1, msg1, &cell); + tt_int_op(r, OP_EQ, -1); + + // Too long for v1 with no stream ID. + msg1->command = RELAY_COMMAND_EXTENDED; + msg1->stream_id = 0; + msg1->length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE_V1_NO_STREAM_ID + 1; + r = relay_msg_encode_cell(RELAY_CELL_FORMAT_V1, msg1, &cell); + tt_int_op(r, OP_EQ, -1); + + // Invalid (present) stream ID for V1. + msg1->stream_id = 10; + msg1->length = 20; + r = relay_msg_encode_cell(RELAY_CELL_FORMAT_V1, msg1, &cell); + tt_int_op(r, OP_EQ, -1); + + // Invalid (absent) stream ID for V1. + msg1->stream_id = 0; + msg1->command = RELAY_COMMAND_DATA; + r = relay_msg_encode_cell(RELAY_CELL_FORMAT_V1, msg1, &cell); + tt_int_op(r, OP_EQ, -1); + + done: + tor_end_capture_bugs_(); + relay_msg_free(msg1); +#endif +} + +static void +test_cfmt_relay_msg_decoding_simple(void *arg) +{ + (void) arg; + cell_t cell; + relay_msg_t *msg1 = NULL; + const char *s; + + memset(&cell, 0, sizeof(cell)); + cell.command = CELL_RELAY; + + // V0 decoding, short message. + s = "02" "0000" "0250" "00000000" "000B" + "68656c6c6f20776f726c64" "00000000"; + base16_decode((char*)cell.payload, sizeof(cell.payload), s, strlen(s)); + msg1 = relay_msg_decode_cell(RELAY_CELL_FORMAT_V0, &cell); + tt_assert(msg1); + + tt_int_op(msg1->command, OP_EQ, RELAY_COMMAND_DATA); + tt_int_op(msg1->stream_id, OP_EQ, 0x250); + tt_int_op(msg1->length, OP_EQ, 11); + tt_mem_op(msg1->body, OP_EQ, "hello world", 11); + relay_msg_free(msg1); + + // V0 decoding, message up to length of cell. + memset(cell.payload, 0, sizeof(cell.payload)); + s = "02" "0000" "0250" "00000000" "01F2"; + base16_decode((char*)cell.payload, sizeof(cell.payload), s, strlen(s)); + msg1 = relay_msg_decode_cell(RELAY_CELL_FORMAT_V0, &cell); + tt_assert(msg1); + + tt_int_op(msg1->command, OP_EQ, RELAY_COMMAND_DATA); + tt_int_op(msg1->stream_id, OP_EQ, 0x250); + tt_int_op(msg1->length, OP_EQ, 498); + tt_assert(fast_mem_is_zero((char*)msg1->body, 498)); + relay_msg_free(msg1); + + // V1 decoding, short message, no stream ID. + s = "00000000000000000000000000000000" + "05" "0014" + "68656c6c6f206920616d2061207461672e2e2e2e" "00000000"; + base16_decode((char*)cell.payload, sizeof(cell.payload), s, strlen(s)); + + msg1 = relay_msg_decode_cell(RELAY_CELL_FORMAT_V1, &cell); + tt_assert(msg1); + tt_int_op(msg1->command, OP_EQ, RELAY_COMMAND_SENDME); + tt_int_op(msg1->stream_id, OP_EQ, 0); + tt_int_op(msg1->length, OP_EQ, 20); + tt_mem_op(msg1->body, OP_EQ, "hello i am a tag....", 20); + relay_msg_free(msg1); + + // V1 decoding, up to length of cell, no stream ID. + memset(cell.payload, 0, sizeof(cell.payload)); + s = "00000000000000000000000000000000" + "05" "01EA"; + base16_decode((char*)cell.payload, sizeof(cell.payload), s, strlen(s)); + + msg1 = relay_msg_decode_cell(RELAY_CELL_FORMAT_V1, &cell); + tt_assert(msg1); + tt_int_op(msg1->command, OP_EQ, RELAY_COMMAND_SENDME); + tt_int_op(msg1->stream_id, OP_EQ, 0); + tt_int_op(msg1->length, OP_EQ, 490); + tt_assert(fast_mem_is_zero((char*)msg1->body, 490)); + relay_msg_free(msg1); + + // V1 decoding, short message, with stream ID. + s = "00000000000000000000000000000000" + "02" "000B" "0250" + "68656c6c6f20776f726c64" "00000000"; + base16_decode((char*)cell.payload, sizeof(cell.payload), s, strlen(s)); + + msg1 = relay_msg_decode_cell(RELAY_CELL_FORMAT_V1, &cell); + tt_assert(msg1); + tt_int_op(msg1->command, OP_EQ, RELAY_COMMAND_DATA); + tt_int_op(msg1->stream_id, OP_EQ, 0x250); + tt_int_op(msg1->length, OP_EQ, 11); + tt_mem_op(msg1->body, OP_EQ, "hello world", 11); + relay_msg_free(msg1); + + // V1 decoding, up to length of cell, with stream ID. + memset(cell.payload, 0, sizeof(cell.payload)); + s = "00000000000000000000000000000000" + "02" "01E8" "0250"; + base16_decode((char*)cell.payload, sizeof(cell.payload), s, strlen(s)); + + msg1 = relay_msg_decode_cell(RELAY_CELL_FORMAT_V1, &cell); + tt_assert(msg1); + tt_int_op(msg1->command, OP_EQ, RELAY_COMMAND_DATA); + tt_int_op(msg1->stream_id, OP_EQ, 0x250); + tt_int_op(msg1->length, OP_EQ, 488); + tt_assert(fast_mem_is_zero((char*)msg1->body, 488)); + relay_msg_free(msg1); + + done: + relay_msg_free(msg1); +} + +static void +test_cfmt_relay_msg_decoding_error(void *arg) +{ + (void) arg; + relay_msg_t *msg1 = NULL; + cell_t cell; + const char *s; + memset(&cell, 0, sizeof(cell)); + + // V0, too long. + cell.command = CELL_RELAY; + s = "02" "0000" "0250" "00000000" "01F3"; + base16_decode((char*)cell.payload, sizeof(cell.payload), s, strlen(s)); + msg1 = relay_msg_decode_cell(RELAY_CELL_FORMAT_V0, &cell); + tt_ptr_op(msg1, OP_EQ, NULL); + + // V1, command unrecognized. + s = "00000000000000000000000000000000" + "F0" "000C" "0250"; + base16_decode((char*)cell.payload, sizeof(cell.payload), s, strlen(s)); + msg1 = relay_msg_decode_cell(RELAY_CELL_FORMAT_V1, &cell); + tt_ptr_op(msg1, OP_EQ, NULL); + + // V1, too long (with stream ID) + s = "00000000000000000000000000000000" + "02" "01E9" "0250"; + base16_decode((char*)cell.payload, sizeof(cell.payload), s, strlen(s)); + msg1 = relay_msg_decode_cell(RELAY_CELL_FORMAT_V1, &cell); + tt_ptr_op(msg1, OP_EQ, NULL); + + // V1, too long (without stream ID) + s = "00000000000000000000000000000000" + "05" "01EB"; + base16_decode((char*)cell.payload, sizeof(cell.payload), s, strlen(s)); + msg1 = relay_msg_decode_cell(RELAY_CELL_FORMAT_V1, &cell); + tt_ptr_op(msg1, OP_EQ, NULL); + + done: + relay_msg_free(msg1); +} + #define TEST(name, flags) \ { #name, test_cfmt_ ## name, flags, 0, NULL } @@ -1340,5 +1607,10 @@ TEST(extended_cells, 0), TEST(resolved_cells, 0), TEST(is_destroy, 0), + TEST(relay_msg_encoding_simple, 0), + TEST(relay_cell_padding, 0), + TEST(relay_msg_encoding_error, 0), + TEST(relay_msg_decoding_simple, 0), + TEST(relay_msg_decoding_error, 0), END_OF_TESTCASES }; diff -Nru tor-0.4.8.16/src/test/test_circuitbuild.c tor-0.4.9.6/src/test/test_circuitbuild.c --- tor-0.4.8.16/src/test/test_circuitbuild.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_circuitbuild.c 2026-03-25 14:30:34.000000000 +0000 @@ -21,6 +21,7 @@ #include "core/or/circuitlist.h" #include "core/or/circuituse.h" #include "core/or/onion.h" +#include "core/or/relay_msg.h" #include "core/or/cell_st.h" #include "core/or/cpath_build_state_st.h" @@ -1278,7 +1279,7 @@ test_circuit_extend(void *arg) { (void)arg; - cell_t *cell = tor_malloc_zero(sizeof(cell_t)); + relay_msg_t *msg = tor_malloc_zero(sizeof(relay_msg_t)); channel_t *p_chan = tor_malloc_zero(sizeof(channel_t)); or_circuit_t *or_circ = tor_malloc_zero(sizeof(or_circuit_t)); circuit_t *circ = TO_CIRCUIT(or_circ); @@ -1293,10 +1294,14 @@ setup_full_capture_of_logs(LOG_INFO); + msg->command = RELAY_COMMAND_EXTEND2; + NONSTRING uint8_t body[3] = "xyz"; + msg->body = body; + #ifndef ALL_BUGS_ARE_FATAL /* Circuit must be non-NULL */ tor_capture_bugs_(1); - tt_int_op(circuit_extend(cell, NULL), OP_EQ, -1); + tt_int_op(circuit_extend(msg, NULL), OP_EQ, -1); tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1); tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ, "!(ASSERT_PREDICT_UNLIKELY_(!circ))"); @@ -1308,7 +1313,7 @@ tt_int_op(circuit_extend(NULL, circ), OP_EQ, -1); tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1); tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ, - "!(ASSERT_PREDICT_UNLIKELY_(!cell))"); + "!(ASSERT_PREDICT_UNLIKELY_(!rmsg))"); tor_end_capture_bugs_(); mock_clean_saved_logs(); @@ -1324,13 +1329,13 @@ /* Clients can't extend */ server = 0; - tt_int_op(circuit_extend(cell, circ), OP_EQ, -1); + tt_int_op(circuit_extend(msg, circ), OP_EQ, -1); expect_log_msg("Got an extend cell, but running as a client. Closing.\n"); mock_clean_saved_logs(); /* But servers can. Unpack the cell, but fail parsing. */ server = 1; - tt_int_op(circuit_extend(cell, circ), OP_EQ, -1); + tt_int_op(circuit_extend(msg, circ), OP_EQ, -1); expect_log_msg("Can't parse extend cell. Closing circuit.\n"); mock_clean_saved_logs(); @@ -1343,7 +1348,7 @@ mock_extend_cell_parse_result = 0; mock_extend_cell_parse_calls = 0; - tt_int_op(circuit_extend(cell, circ), OP_EQ, -1); + tt_int_op(circuit_extend(msg, circ), OP_EQ, -1); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); expect_log_msg( "Client asked me to extend without specifying an id_digest.\n"); @@ -1354,7 +1359,7 @@ memset(&mock_extend_cell_parse_cell_out.node_id, 0xAA, sizeof(mock_extend_cell_parse_cell_out.node_id)); - tt_int_op(circuit_extend(cell, circ), OP_EQ, -1); + tt_int_op(circuit_extend(msg, circ), OP_EQ, -1); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); expect_log_msg("Client asked me to extend to a zero destination port " "or unspecified address '[scrubbed]'.\n"); @@ -1368,7 +1373,7 @@ #ifndef ALL_BUGS_ARE_FATAL tor_capture_bugs_(1); - tt_int_op(circuit_extend(cell, circ), OP_EQ, -1); + tt_int_op(circuit_extend(msg, circ), OP_EQ, -1); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1); tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ, @@ -1389,7 +1394,7 @@ /* Test circuit not established, but don't launch another one */ mock_channel_get_for_extend_launch_out = 0; mock_channel_get_for_extend_nchan = NULL; - tt_int_op(circuit_extend(cell, circ), OP_EQ, 0); + tt_int_op(circuit_extend(msg, circ), OP_EQ, 0); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); tt_int_op(mock_channel_get_for_extend_calls, OP_EQ, 1); @@ -1409,7 +1414,7 @@ mock_channel_get_for_extend_launch_out = 1; mock_channel_get_for_extend_nchan = NULL; mock_channel_connect_nchan = fake_n_chan; - tt_int_op(circuit_extend(cell, circ), OP_EQ, 0); + tt_int_op(circuit_extend(msg, circ), OP_EQ, 0); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); tt_int_op(mock_channel_get_for_extend_calls, OP_EQ, 1); tt_int_op(mock_channel_connect_calls, OP_EQ, 1); @@ -1433,7 +1438,7 @@ mock_channel_get_for_extend_nchan = fake_n_chan; mock_channel_connect_nchan = NULL; mock_circuit_deliver_create_cell_result = 0; - tt_int_op(circuit_extend(cell, circ), OP_EQ, 0); + tt_int_op(circuit_extend(msg, circ), OP_EQ, 0); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); tt_int_op(mock_channel_get_for_extend_calls, OP_EQ, 1); tt_int_op(mock_channel_connect_calls, OP_EQ, 0); @@ -1456,7 +1461,7 @@ mock_channel_get_for_extend_nchan = fake_n_chan; mock_channel_connect_nchan = NULL; mock_circuit_deliver_create_cell_result = -1; - tt_int_op(circuit_extend(cell, circ), OP_EQ, -1); + tt_int_op(circuit_extend(msg, circ), OP_EQ, -1); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); tt_int_op(mock_channel_get_for_extend_calls, OP_EQ, 1); tt_int_op(mock_channel_connect_calls, OP_EQ, 0); @@ -1502,7 +1507,7 @@ mock_circuit_deliver_create_cell_calls = 0; mock_circuit_deliver_create_cell_result = 0; - tor_free(cell); + relay_msg_free(msg); /* circ and or_circ are the same object */ tor_free(circ->n_hop); tor_free(circ->n_chan_create_cell); @@ -1527,6 +1532,7 @@ /* Circuit must be non-NULL */ tor_capture_bugs_(1); tt_int_op(onionskin_answer(NULL, created_cell, + RELAY_CRYPTO_ALG_TOR1, keys, CPATH_KEY_MATERIAL_LEN, rend_circ_nonce), OP_EQ, -1); tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1); @@ -1538,6 +1544,7 @@ /* Created cell must be non-NULL */ tor_capture_bugs_(1); tt_int_op(onionskin_answer(or_circ, NULL, + RELAY_CRYPTO_ALG_TOR1, keys, CPATH_KEY_MATERIAL_LEN, rend_circ_nonce), OP_EQ, -1); tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1); @@ -1549,6 +1556,7 @@ /* Keys must be non-NULL */ tor_capture_bugs_(1); tt_int_op(onionskin_answer(or_circ, created_cell, + RELAY_CRYPTO_ALG_TOR1, NULL, CPATH_KEY_MATERIAL_LEN, rend_circ_nonce), OP_EQ, -1); tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1); @@ -1560,6 +1568,7 @@ /* The rend circuit nonce must be non-NULL */ tor_capture_bugs_(1); tt_int_op(onionskin_answer(or_circ, created_cell, + RELAY_CRYPTO_ALG_TOR1, keys, CPATH_KEY_MATERIAL_LEN, NULL), OP_EQ, -1); tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1); @@ -1574,6 +1583,7 @@ /* Fail when formatting the created cell */ tt_int_op(onionskin_answer(or_circ, created_cell, + RELAY_CRYPTO_ALG_TOR1, keys, CPATH_KEY_MATERIAL_LEN, rend_circ_nonce), OP_EQ, -1); expect_log_msg("couldn't format created cell (type=0, len=0).\n"); diff -Nru tor-0.4.8.16/src/test/test_circuitlist.c tor-0.4.9.6/src/test/test_circuitlist.c --- tor-0.4.8.16/src/test/test_circuitlist.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_circuitlist.c 2026-03-25 14:30:34.000000000 +0000 @@ -187,9 +187,9 @@ { or_circuit_t *c1, *c2, *c3, *c4; origin_circuit_t *c5; - const uint8_t tok1[REND_TOKEN_LEN] = "The cat can't tell y"; - const uint8_t tok2[REND_TOKEN_LEN] = "ou its name, and it "; - const uint8_t tok3[REND_TOKEN_LEN] = "doesn't really care."; + NONSTRING const uint8_t tok1[REND_TOKEN_LEN] = "The cat can't tell y"; + NONSTRING const uint8_t tok2[REND_TOKEN_LEN] = "ou its name, and it "; + NONSTRING const uint8_t tok3[REND_TOKEN_LEN] = "doesn't really care."; /* -- Adapted from a quote by Fredrik Lundh. */ (void)arg; @@ -420,7 +420,7 @@ ed25519_public_key_t intro_pk2 = { {2} }; /* Junk, not important. */ { - const uint8_t tok1[REND_TOKEN_LEN] = "bet i got some of th"; + NONSTRING const uint8_t tok1[REND_TOKEN_LEN] = "bet i got some of th"; circ1 = or_circuit_new(0, NULL); tt_assert(circ1); @@ -442,7 +442,7 @@ } { - const uint8_t tok2[REND_TOKEN_LEN] = "you dont know anythi"; + NONSTRING const uint8_t tok2[REND_TOKEN_LEN] = "you dont know anythi"; circ2 = origin_circuit_new(); tt_assert(circ2); diff -Nru tor-0.4.8.16/src/test/test_circuitpadding.c tor-0.4.9.6/src/test/test_circuitpadding.c --- tor-0.4.8.16/src/test/test_circuitpadding.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_circuitpadding.c 2026-03-25 14:30:34.000000000 +0000 @@ -24,6 +24,7 @@ #include "core/or/circuitpadding.h" #include "core/or/circuitpadding_machines.h" #include "core/or/extendinfo.h" +#include "core/or/relay_msg.h" #include "core/mainloop/netstatus.h" #include "core/crypto/relay_crypto.h" #include "core/or/protover.h" @@ -172,11 +173,16 @@ const char *filename, int lineno) { (void)cell; (void)on_stream; (void)filename; (void)lineno; + relay_msg_t *msg = NULL; + + msg = relay_msg_decode_cell(RELAY_CELL_FORMAT_V0, cell); + if (! msg) + goto done; if (circ == client_side) { if (cell->payload[0] == RELAY_COMMAND_PADDING_NEGOTIATE) { // Deliver to relay - circpad_handle_padding_negotiate(relay_side, cell); + circpad_handle_padding_negotiate(relay_side, msg); } else { int is_target_hop = circpad_padding_is_from_expected_hop(circ, @@ -190,7 +196,7 @@ // Receive padding cell at middle circpad_deliver_recognized_relay_cell_events(relay_side, - cell->payload[0], NULL); + msg->command, NULL); } n_client_cells++; } else if (circ == relay_side) { @@ -199,11 +205,11 @@ if (cell->payload[0] == RELAY_COMMAND_PADDING_NEGOTIATED) { // XXX: blah need right layer_hint.. if (deliver_negotiated) - circpad_handle_padding_negotiated(client_side, cell, + circpad_handle_padding_negotiated(client_side, msg, TO_ORIGIN_CIRCUIT(client_side) ->cpath->next); } else if (cell->payload[0] == RELAY_COMMAND_PADDING_NEGOTIATE) { - circpad_handle_padding_negotiate(client_side, cell); + circpad_handle_padding_negotiate(client_side, msg); } else { // No need to pretend a padding cell was sent: This event is // now emitted internally when the circuitpadding code sends them. @@ -211,7 +217,7 @@ // Receive padding cell at client circpad_deliver_recognized_relay_cell_events(client_side, - cell->payload[0], + msg->command, TO_ORIGIN_CIRCUIT(client_side)->cpath->next); } @@ -219,6 +225,7 @@ } done: + relay_msg_free(msg); timers_advance_and_run(1); return 0; } @@ -1251,7 +1258,7 @@ */ (void)arg; uint32_t read_bw = 0, overhead_bw = 0; - cell_t cell; + relay_msg_t msg; signed_error_t ret; origin_circuit_t *orig_client; int64_t actual_mocked_monotime_start; @@ -1331,17 +1338,21 @@ orig_client->n_overhead_read_circ_bw); /* 2. Test padding negotiated not handled from hops 1,3 */ - ret = circpad_handle_padding_negotiated(client_side, &cell, + memset(&msg, 0, sizeof(msg)); + ret = circpad_handle_padding_negotiated(client_side, &msg, TO_ORIGIN_CIRCUIT(client_side)->cpath); tt_int_op(ret, OP_EQ, -1); - ret = circpad_handle_padding_negotiated(client_side, &cell, + ret = circpad_handle_padding_negotiated(client_side, &msg, TO_ORIGIN_CIRCUIT(client_side)->cpath->next->next); tt_int_op(ret, OP_EQ, -1); /* 3. Garbled negotiated cell */ - memset(&cell, 255, sizeof(cell)); - ret = circpad_handle_padding_negotiated(client_side, &cell, + memset(&msg, 0, sizeof(msg)); + uint8_t buf[99]; + memset(buf, 0xff, 99); + msg.body = buf; + ret = circpad_handle_padding_negotiated(client_side, &msg, TO_ORIGIN_CIRCUIT(client_side)->cpath->next); tt_int_op(ret, OP_EQ, -1); @@ -1350,7 +1361,7 @@ overhead_bw = orig_client->n_overhead_read_circ_bw; relay_send_command_from_edge(0, relay_side, RELAY_COMMAND_PADDING_NEGOTIATE, - (void*)cell.payload, + "xyz", (size_t)3, NULL); tt_int_op(read_bw, OP_EQ, orig_client->n_delivered_read_circ_bw); @@ -1371,12 +1382,12 @@ tt_int_op(n_client_cells, OP_EQ, 2); /* 6. Sending negotiated command to relay does nothing */ - ret = circpad_handle_padding_negotiated(relay_side, &cell, NULL); + ret = circpad_handle_padding_negotiated(relay_side, &msg, NULL); tt_int_op(ret, OP_EQ, -1); /* 7. Test garbled negotiated cell (bad command 255) */ - memset(&cell, 0, sizeof(cell)); - ret = circpad_handle_padding_negotiate(relay_side, &cell); + relay_msg_clear(&msg); + ret = circpad_handle_padding_negotiate(relay_side, &msg); tt_int_op(ret, OP_EQ, -1); tt_int_op(n_client_cells, OP_EQ, 2); @@ -1434,6 +1445,7 @@ UNMOCK(circuitmux_attach_circuit); nodes_free(); testing_disable_reproducible_rng(); + relay_msg_clear(&msg); } void @@ -1576,7 +1588,7 @@ { char whatevs_key[CPATH_KEY_MATERIAL_LEN]; char digest[DIGEST_LEN]; - tor_addr_t addr; + tor_addr_t addr = TOR_ADDR_NULL; // Pretend a non-padding cell was sent circpad_cell_event_nonpadding_sent(client); @@ -1608,10 +1620,11 @@ hop->extend_info = extend_info_new( padding ? "padding" : "non-padding", - digest, NULL, NULL, NULL, + digest, NULL, NULL, &addr, padding, NULL, false); - cpath_init_circuit_crypto(hop, whatevs_key, sizeof(whatevs_key), 0, 0); + cpath_init_circuit_crypto(RELAY_CRYPTO_ALG_TOR1, hop, + whatevs_key, sizeof(whatevs_key)); hop->package_window = circuit_initial_package_window(); hop->deliver_window = CIRCWINDOW_START; @@ -3100,17 +3113,18 @@ test_circuitpadding_ignore_non_padding_cells(void *arg) { int retval; - relay_header_t rh; (void) arg; client_side = (circuit_t *)origin_circuit_new(); client_side->purpose = CIRCUIT_PURPOSE_C_CIRCUIT_PADDING; - rh.command = RELAY_COMMAND_BEGIN; + relay_msg_t msg; + memset(&msg, 0, sizeof(msg)); + msg.command = RELAY_COMMAND_BEGIN; setup_full_capture_of_logs(LOG_INFO); - retval = handle_relay_cell_command(NULL, client_side, NULL, NULL, &rh, 0); + retval = handle_relay_msg(&msg, client_side, NULL, NULL, 0); tt_int_op(retval, OP_EQ, 0); expect_log_msg_containing("Ignored cell"); diff -Nru tor-0.4.8.16/src/test/test_config.c tor-0.4.9.6/src/test/test_config.c --- tor-0.4.8.16/src/test/test_config.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_config.c 2026-03-25 14:30:34.000000000 +0000 @@ -6321,14 +6321,14 @@ tt_int_op(check_bridge_distribution_setting("any"), OP_EQ, 0); tt_int_op(check_bridge_distribution_setting("https"), OP_EQ, 0); tt_int_op(check_bridge_distribution_setting("email"), OP_EQ, 0); - tt_int_op(check_bridge_distribution_setting("moat"), OP_EQ, 0); + tt_int_op(check_bridge_distribution_setting("settings"), OP_EQ, 0); // Check all the possible values we support right now with weird casing. tt_int_op(check_bridge_distribution_setting("NoNe"), OP_EQ, 0); tt_int_op(check_bridge_distribution_setting("anY"), OP_EQ, 0); tt_int_op(check_bridge_distribution_setting("hTTps"), OP_EQ, 0); tt_int_op(check_bridge_distribution_setting("emAIl"), OP_EQ, 0); - tt_int_op(check_bridge_distribution_setting("moAt"), OP_EQ, 0); + tt_int_op(check_bridge_distribution_setting("setTIngS"), OP_EQ, 0); // Invalid values. tt_int_op(check_bridge_distribution_setting("x\rx"), OP_EQ, -1); diff -Nru tor-0.4.8.16/src/test/test_conflux_cell.c tor-0.4.9.6/src/test/test_conflux_cell.c --- tor-0.4.8.16/src/test/test_conflux_cell.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_conflux_cell.c 2026-03-25 14:30:34.000000000 +0000 @@ -13,15 +13,19 @@ #include "core/or/conflux_cell.h" #include "core/or/conflux_st.h" #include "trunnel/conflux.h" +#include "core/or/relay_msg.h" +#include "core/or/relay_msg_st.h" #include "lib/crypt_ops/crypto_rand.h" static void test_link(void *arg) { - cell_t cell; conflux_cell_link_t link; conflux_cell_link_t *decoded_link = NULL; + relay_msg_t msg; + uint8_t buf0[RELAY_PAYLOAD_SIZE_MAX]; + uint8_t buf1[RELAY_PAYLOAD_SIZE_MAX]; (void) arg; @@ -34,14 +38,15 @@ crypto_rand((char *) link.nonce, sizeof(link.nonce)); - ssize_t cell_len = build_link_cell(&link, cell.payload+RELAY_HEADER_SIZE); + ssize_t cell_len = build_link_cell(&link, buf0); tt_int_op(cell_len, OP_GT, 0); + msg.length = cell_len; + msg.body = buf0; - decoded_link = conflux_cell_parse_link(&cell, cell_len); + decoded_link = conflux_cell_parse_link(&msg); tt_assert(decoded_link); - uint8_t buf[RELAY_PAYLOAD_SIZE]; - ssize_t enc_cell_len = build_link_cell(decoded_link, buf); + ssize_t enc_cell_len = build_link_cell(decoded_link, buf1); tt_int_op(cell_len, OP_EQ, enc_cell_len); /* Validate the original link object with the decoded one. */ @@ -49,6 +54,7 @@ tor_free(decoded_link); done: + relay_msg_clear(&msg); tor_free(decoded_link); } @@ -57,4 +63,3 @@ END_OF_TESTCASES }; - diff -Nru tor-0.4.8.16/src/test/test_conflux_pool.c tor-0.4.9.6/src/test/test_conflux_pool.c --- tor-0.4.8.16/src/test/test_conflux_pool.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_conflux_pool.c 2026-03-25 14:30:34.000000000 +0000 @@ -29,6 +29,7 @@ #include "core/or/congestion_control_st.h" #include "core/or/congestion_control_common.h" #include "core/or/extendinfo.h" +#include "core/or/relay_msg.h" #include "core/mainloop/netstatus.h" #include "core/crypto/relay_crypto.h" #include "core/or/protover.h" @@ -223,6 +224,7 @@ process_mock_cell_delivery(void) { relay_header_t rh; + relay_msg_t *msg = NULL; cell_delivery_t *delivery = smartlist_pop_last(mock_cell_delivery); tor_assert(delivery); @@ -232,16 +234,20 @@ timers_advance_and_run(1); - switch (cell->payload[0]) { + msg = relay_msg_decode_cell(RELAY_CELL_FORMAT_V0, cell); + + tor_assert(msg); + + switch (msg->command) { case RELAY_COMMAND_CONFLUX_LINK: tor_assert(!CIRCUIT_IS_ORIGIN(dest_circ)); - conflux_process_link(dest_circ, cell, rh.length); + conflux_process_link(dest_circ, msg); break; case RELAY_COMMAND_CONFLUX_LINKED: tor_assert(CIRCUIT_IS_ORIGIN(dest_circ)); conflux_process_linked(dest_circ, TO_ORIGIN_CIRCUIT(dest_circ)->cpath->prev, - cell, rh.length); + msg); break; case RELAY_COMMAND_CONFLUX_LINKED_ACK: tor_assert(!CIRCUIT_IS_ORIGIN(dest_circ)); @@ -253,12 +259,13 @@ // the case where the switch is initiated by the exit, we will need to // get the cpath layer hint for the client. tor_assert(!CIRCUIT_IS_ORIGIN(dest_circ)); - conflux_process_switch_command(dest_circ, NULL, cell, &rh); + conflux_process_switch_command(dest_circ, NULL, msg); break; } tor_free(delivery); tor_free(cell); + relay_msg_free(msg); return; } @@ -329,7 +336,7 @@ { char whatevs_key[CPATH_KEY_MATERIAL_LEN]; char digest[DIGEST_LEN]; - tor_addr_t addr; + tor_addr_t addr = TOR_ADDR_NULL; // Advance time a tiny bit so we can calculate an RTT curr_mocked_time += 10 * TOR_NSEC_PER_MSEC; @@ -349,10 +356,11 @@ hop->extend_info = extend_info_new( exit ? "exit" : "non-exit", - digest, NULL, NULL, NULL, + digest, NULL, NULL, &addr, exit, NULL, exit); - cpath_init_circuit_crypto(hop, whatevs_key, sizeof(whatevs_key), 0, 0); + cpath_init_circuit_crypto(RELAY_CRYPTO_ALG_TOR1, hop, + whatevs_key, sizeof(whatevs_key)); hop->package_window = circuit_initial_package_window(); hop->deliver_window = CIRCWINDOW_START; @@ -396,6 +404,7 @@ static void test_clear_circs(void) { + conflux_notify_shutdown(); SMARTLIST_FOREACH(circ_pairs, circ_pair_t *, circ_pair, { tor_free(circ_pair); }); @@ -430,6 +439,9 @@ tor_assert(smartlist_len(mock_cell_delivery) == 0); (void)free_fake_origin_circuit; + + /* Clear shutdown flag so we can resume testing again. */ + conflux_clear_shutdown(); } static void diff -Nru tor-0.4.8.16/src/test/test_crypto.c tor-0.4.9.6/src/test/test_crypto.c --- tor-0.4.8.16/src/test/test_crypto.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_crypto.c 2026-03-25 14:30:34.000000000 +0000 @@ -6,6 +6,8 @@ #include "orconfig.h" #define CRYPTO_CURVE25519_PRIVATE #define CRYPTO_RAND_PRIVATE +#define USE_AES_RAW +#define TOR_AES_PRIVATE #include "core/or/or.h" #include "test/test.h" #include "lib/crypt_ops/aes.h" @@ -21,6 +23,7 @@ #include "lib/crypt_ops/crypto_init.h" #include "ed25519_vectors.inc" #include "test/log_test_helpers.h" +#include "ext/polyval/polyval.h" #ifdef HAVE_SYS_STAT_H #include @@ -43,10 +46,10 @@ crypto_dh_t *dh1 = crypto_dh_new(DH_TYPE_CIRCUIT); crypto_dh_t *dh1_dup = NULL; crypto_dh_t *dh2 = crypto_dh_new(DH_TYPE_CIRCUIT); - char p1[DH1024_KEY_LEN]; - char p2[DH1024_KEY_LEN]; - char s1[DH1024_KEY_LEN]; - char s2[DH1024_KEY_LEN]; + char p1[DH2048_KEY_LEN]; + char p2[DH2048_KEY_LEN]; + char s1[DH2048_KEY_LEN]; + char s2[DH2048_KEY_LEN]; ssize_t s1len, s2len; #ifdef ENABLE_OPENSSL crypto_dh_t *dh3 = NULL; @@ -182,27 +185,23 @@ { /* Make sure that our crypto library can handshake with openssl. */ dh3 = crypto_dh_new(DH_TYPE_TLS); - tt_assert(!crypto_dh_get_public(dh3, p1, DH1024_KEY_LEN)); + tt_assert(!crypto_dh_get_public(dh3, p1, sizeof(p1))); dh4 = crypto_dh_new_openssl_tls(); tt_assert(DH_generate_key(dh4)); const BIGNUM *pk=NULL; -#ifdef OPENSSL_1_1_API const BIGNUM *sk=NULL; DH_get0_key(dh4, &pk, &sk); -#else - pk = dh4->pub_key; -#endif /* defined(OPENSSL_1_1_API) */ tt_assert(pk); - tt_int_op(BN_num_bytes(pk), OP_LE, DH1024_KEY_LEN); + tt_int_op(BN_num_bytes(pk), OP_LE, DH_TLS_KEY_BITS / 8); tt_int_op(BN_num_bytes(pk), OP_GT, 0); memset(p2, 0, sizeof(p2)); /* right-pad. */ - BN_bn2bin(pk, (unsigned char *)(p2+DH1024_KEY_LEN-BN_num_bytes(pk))); + BN_bn2bin(pk, (unsigned char *)(p2+sizeof(p2)-BN_num_bytes(pk))); - s1len = crypto_dh_handshake(LOG_WARN, dh3, p2, DH1024_KEY_LEN, + s1len = crypto_dh_handshake(LOG_WARN, dh3, p2, DH_TLS_KEY_BITS / 8, (unsigned char *)s1, sizeof(s1)); - pubkey_tmp = BN_bin2bn((unsigned char *)p1, DH1024_KEY_LEN, NULL); + pubkey_tmp = BN_bin2bn((unsigned char *)p1, DH_TLS_KEY_BITS / 8, NULL); s2len = DH_compute_key((unsigned char *)s2, pubkey_tmp, dh4); tt_int_op(s1len, OP_EQ, s2len); @@ -260,14 +259,12 @@ static void test_crypto_aes128(void *arg) { + (void)arg; char *data1 = NULL, *data2 = NULL, *data3 = NULL; crypto_cipher_t *env1 = NULL, *env2 = NULL; int i, j; char *mem_op_hex_tmp=NULL; char key[CIPHER_KEY_LEN]; - int use_evp = !strcmp(arg,"evp"); - evaluate_evp_for_aes(use_evp); - evaluate_ctr_for_aes(); data1 = tor_malloc(1024); data2 = tor_malloc(1024); @@ -1635,14 +1632,12 @@ static void test_crypto_aes_iv(void *arg) { + (void)arg; char *plain, *encrypted1, *encrypted2, *decrypted1, *decrypted2; char plain_1[1], plain_15[15], plain_16[16], plain_17[17]; char key1[16], key2[16]; ssize_t encrypted_size, decrypted_size; - int use_evp = !strcmp(arg,"evp"); - evaluate_evp_for_aes(use_evp); - plain = tor_malloc(4095); encrypted1 = tor_malloc(4095 + 1 + 16); encrypted2 = tor_malloc(4095 + 1 + 16); @@ -3192,6 +3187,253 @@ ; } +static void +test_crypto_polyval(void *arg) +{ + (void)arg; + polyval_t pv; + uint8_t key[16]; + uint8_t input[48]; + uint8_t output[16]; + uint8_t output2[16]; + char *mem_op_hex_tmp=NULL; + uint8_t *longer = NULL; + + // From RFC 8452 + const char *key_hex = "25629347589242761d31f826ba4b757b"; + const char *input_hex = + "4f4f95668c83dfb6401762bb2d01a262" + "d1a24ddd2721d006bbe45f20d3c9f362"; + memset(input, 0, sizeof(input)); + base16_decode((char*)key,sizeof(key), key_hex, strlen(key_hex)); + base16_decode((char*)input,sizeof(input), input_hex, strlen(input_hex)); + + // Two blocks, directly. + polyval_init(&pv, key); + polyval_add_block(&pv, input); + polyval_add_block(&pv, input+16); + polyval_get_tag(&pv, output); + test_memeq_hex(output, "f7a3b47b846119fae5b7866cf5e5b77e"); + // Two blocks, as a string. + polyval_reset(&pv); + polyval_add_zpad(&pv, input, 32); + polyval_get_tag(&pv, output); + test_memeq_hex(output, "f7a3b47b846119fae5b7866cf5e5b77e"); + + // Now make sure that zero-padding works. + input[32] = 77; + polyval_reset(&pv); + polyval_add_block(&pv, input); + polyval_add_block(&pv, input+16); + polyval_add_block(&pv, input+32); + polyval_get_tag(&pv, output); + + polyval_reset(&pv); + polyval_add_zpad(&pv, input, 33); + polyval_get_tag(&pv, output2); + tt_mem_op(output, OP_EQ, output2, 16); + + // Try a long input both ways, and make sure the answer is the same. + longer = tor_malloc_zero(4096); + crypto_rand((char *)longer, 4090); // leave zeros at the end. + polyval_reset(&pv); + polyval_add_zpad(&pv, longer, 4090); + polyval_get_tag(&pv, output); + + polyval_reset(&pv); + const uint8_t *cp; + for (cp = longer; cp < longer + 4096; cp += 16) { + polyval_add_block(&pv, cp); + } + polyval_get_tag(&pv, output2); + tt_mem_op(output, OP_EQ, output2, 16); + + // Now the same with polyvalx. + polyvalx_t pvx; + polyvalx_init(&pvx, key); + polyvalx_add_zpad(&pvx, longer, 4090); + polyvalx_get_tag(&pvx, output2); + tt_mem_op(output, OP_EQ, output2, 16); + + polyvalx_reset(&pvx); + for (cp = longer; cp < longer + 4096; cp += 16) { + polyvalx_add_block(&pvx, cp); + } + polyvalx_get_tag(&pvx, output2); + tt_mem_op(output, OP_EQ, output2, 16); + + done: + tor_free(mem_op_hex_tmp); + tor_free(longer); +} + +static void +test_aes_raw_one(int keybits, + const char *key_hex, + const char *plaintext_hex, + const char *ciphertext_hex) +{ + aes_raw_t *enc = NULL; + aes_raw_t *dec = NULL; + uint8_t key[32]; // max key size. + uint8_t pt[16], ct[16], block[16]; + tt_int_op(keybits, OP_EQ, strlen(key_hex) * 8 / 2); + base16_decode((char*)key, sizeof(key), key_hex, strlen(key_hex)); + base16_decode((char*)pt, sizeof(pt), plaintext_hex, strlen(plaintext_hex)); + base16_decode((char*)ct, sizeof(ct), ciphertext_hex, strlen(ciphertext_hex)); + + enc = aes_raw_new(key, keybits, true); + dec = aes_raw_new(key, keybits, false); + memcpy(block, pt, sizeof(pt)); + aes_raw_encrypt(enc, block); + tt_mem_op(block, OP_EQ, ct, 16); + aes_raw_decrypt(dec, block); + tt_mem_op(block, OP_EQ, pt, 16); + + done: + aes_raw_free(enc); + aes_raw_free(dec); +} + +static void +test_crypto_aes_raw(void *arg) +{ + (void)arg; + +#define T test_aes_raw_one + + /* From https://csrc.nist.gov/CSRC/media/Projects/ + Cryptographic-Algorithm-Validation-Program/documents/aes/AESAVS.pdf */ + const char *z128 = + "00000000000000000000000000000000"; + const char *z192 = + "00000000000000000000000000000000" + "0000000000000000"; + const char *z256 = + "00000000000000000000000000000000" + "00000000000000000000000000000000"; + + T(128, z128, + "f34481ec3cc627bacd5dc3fb08f273e6", + "0336763e966d92595a567cc9ce537f5e"); + T(192, z192, + "1b077a6af4b7f98229de786d7516b639", + "275cfc0413d8ccb70513c3859b1d0f72"); + T(256, z256, + "014730f80ac625fe84f026c60bfd547d", + "5c9d844ed46f9885085e5d6a4f94c7d7"); + T(128, + "10a58869d74be5a374cf867cfb473859", z128, + "6d251e6944b051e04eaa6fb4dbf78465"); + T(192, + "e9f065d7c13573587f7875357dfbb16c53489f6a4bd0f7cd", z128, + "0956259c9cd5cfd0181cca53380cde06"); + T(256, + "c47b0294dbbbee0fec4757f22ffeee35" + "87ca4730c3d33b691df38bab076bc558", z128, + "46f2fb342d6f0ab477476fc501242c5f"); + +#undef T +} + +/** Make sure that we can set keys on live AES instances correctly. */ +static void +test_crypto_aes_keymanip_cnt(void *arg) +{ + (void) arg; + uint8_t k1[16] = "123456780123678"; + uint8_t k2[16] = "abcdefghijklmno"; + int kbits = 128; + uint8_t iv1[16]= "{return 4;}////"; + uint8_t iv2[16] = {0}; + uint8_t buf[128] = {0}; + uint8_t buf2[128] = {0}; + + aes_cnt_cipher_t *aes = aes_new_cipher(k1, iv1, kbits); + aes_crypt_inplace(aes, (char*)buf, sizeof(buf)); + + aes_cnt_cipher_t *aes2 = aes_new_cipher(k2, iv2, kbits); + // 128-5 to make sure internal buf is cleared when we set key. + aes_crypt_inplace(aes2, (char*)buf2, sizeof(buf2)-5); + aes_cipher_set_key(aes2, k1, kbits); + aes_cipher_set_iv_aligned(aes2, iv1); // should work in this case. + memset(buf2, 0, sizeof(buf2)); + aes_crypt_inplace(aes2, (char*)buf2, sizeof(buf2)); + tt_mem_op(buf, OP_EQ, buf2, sizeof(buf)); + + done: + aes_cipher_free(aes); + aes_cipher_free(aes2); +} + +static void +test_crypto_aes_keymanip_ecb(void *arg) +{ + (void) arg; + uint8_t k1[16] = "123456780123678"; + uint8_t k2[16] = "abcdefghijklmno"; + int kbits = 128; + uint8_t buf_orig[16] = {1,2,3,0}; + uint8_t buf1[16]; + uint8_t buf2[16]; + + aes_raw_t *aes1 = aes_raw_new(k1, kbits, true); + aes_raw_t *aes2 = aes_raw_new(k1, kbits, false); + aes_raw_set_key(&aes2, k2, kbits, false); + + memcpy(buf1, buf_orig, 16); + memcpy(buf2, buf_orig, 16); + + aes_raw_encrypt(aes1, buf1); + aes_raw_encrypt(aes1, buf2); + tt_mem_op(buf1, OP_EQ, buf2, 16); + + aes_raw_decrypt(aes2, buf1); + aes_raw_set_key(&aes2, k1, kbits, false); + aes_raw_decrypt(aes2, buf2); + + tt_mem_op(buf1, OP_NE, buf2, 16); + tt_mem_op(buf2, OP_EQ, buf_orig, 16); + + done: + aes_raw_free(aes1); + aes_raw_free(aes2); +} + +static void +test_crypto_aes_cnt_set_iv(void *arg) +{ + (void)arg; + uint8_t k1[16] = "123456780123678"; + uint8_t iv_zero[16] = {0}; + int kbits = 128; + const int iters = 100; + uint8_t buf1[128]; + uint8_t buf2[128]; + + aes_cnt_cipher_t *aes1, *aes2 = NULL; + aes1 = aes_new_cipher(k1, iv_zero, kbits); + + for (int i = 0; i < iters; ++i) { + uint8_t iv[16]; + crypto_rand((char*) iv, sizeof(iv)); + memset(buf1, 0, sizeof(buf1)); + memset(buf2, 0, sizeof(buf2)); + + aes_cipher_set_iv_aligned(aes1, iv); + aes2 = aes_new_cipher(k1, iv, kbits); + + aes_crypt_inplace(aes1, (char*)buf1, sizeof(buf1)); + aes_crypt_inplace(aes2, (char*)buf1, sizeof(buf2)); + tt_mem_op(buf1, OP_EQ, buf2, sizeof(buf1)); + + aes_cipher_free(aes2); + } + done: + aes_cipher_free(aes1); + aes_cipher_free(aes2); +} + #ifndef COCCI #define CRYPTO_LEGACY(name) \ { #name, test_crypto_ ## name , 0, NULL, NULL } @@ -3208,8 +3450,7 @@ struct testcase_t crypto_tests[] = { CRYPTO_LEGACY(formats), { "openssl_version", test_crypto_openssl_version, TT_FORK, NULL, NULL }, - { "aes_AES", test_crypto_aes128, TT_FORK, &passthrough_setup, (void*)"aes" }, - { "aes_EVP", test_crypto_aes128, TT_FORK, &passthrough_setup, (void*)"evp" }, + { "aes", test_crypto_aes128, TT_FORK, NULL, NULL }, { "aes128_ctr_testvec", test_crypto_aes_ctr_testvec, 0, &passthrough_setup, (void*)"128" }, { "aes192_ctr_testvec", test_crypto_aes_ctr_testvec, 0, @@ -3230,10 +3471,7 @@ { "sha3_xof", test_crypto_sha3_xof, TT_FORK, NULL, NULL}, { "mac_sha3", test_crypto_mac_sha3, TT_FORK, NULL, NULL}, CRYPTO_LEGACY(dh), - { "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &passthrough_setup, - (void*)"aes" }, - { "aes_iv_EVP", test_crypto_aes_iv, TT_FORK, &passthrough_setup, - (void*)"evp" }, + { "aes_iv_EVP", test_crypto_aes_iv, TT_FORK, NULL, NULL }, CRYPTO_LEGACY(base32_decode), { "kdf_TAP", test_crypto_kdf_TAP, 0, NULL, NULL }, { "hkdf_sha256", test_crypto_hkdf_sha256, 0, NULL, NULL }, @@ -3259,5 +3497,10 @@ { "blake2b", test_crypto_blake2b, 0, NULL, NULL }, { "hashx", test_crypto_hashx, 0, NULL, NULL }, { "failure_modes", test_crypto_failure_modes, TT_FORK, NULL, NULL }, + { "polyval", test_crypto_polyval, 0, NULL, NULL }, + { "aes_raw", test_crypto_aes_raw, 0, NULL, NULL }, + { "aes_keymanip_cnt", test_crypto_aes_keymanip_cnt, 0, NULL, NULL }, + { "aes_keymanip_ecb", test_crypto_aes_keymanip_ecb, 0, NULL, NULL }, + { "aes_cnt_set_iv", test_crypto_aes_cnt_set_iv, 0, NULL, NULL }, END_OF_TESTCASES }; diff -Nru tor-0.4.8.16/src/test/test_crypto_cgo.c tor-0.4.9.6/src/test/test_crypto_cgo.c --- tor-0.4.8.16/src/test/test_crypto_cgo.c 1970-01-01 00:00:00.000000000 +0000 +++ tor-0.4.9.6/src/test/test_crypto_cgo.c 2026-03-25 14:30:34.000000000 +0000 @@ -0,0 +1,647 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2021, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define RELAY_CRYPTO_CGO_PRIVATE +#define USE_AES_RAW + +#include "orconfig.h" +#include "core/or/or.h" +#include "test/test.h" +#include "lib/cc/compat_compiler.h" +#include "lib/crypt_ops/aes.h" +#include "ext/polyval/polyval.h" +#include "core/crypto/relay_crypto_cgo.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "lib/crypt_ops/crypto_util.h" +#include "core/or/cell_st.h" + +#include "test/cgo_vectors.inc" + +static const int AESBITS[] = { 128, 192, 256 }; + +static void +test_crypto_cgo_et_roundtrip(void *arg) +{ + (void)arg; + uint8_t key[32 + 16]; // max + uint8_t tweak_h[16]; + uint8_t tweak_x_r[493]; + uint8_t block[16], block_orig[16]; + cgo_et_t et1, et2; + memset(&et1, 0, sizeof(et1)); + memset(&et2, 0, sizeof(et2)); + + et_tweak_t tweak = { + .uiv = { + .h = tweak_h, + .cmd = 7, + }, + .x_r = tweak_x_r, + }; + + for (int bi = 0; bi < (int) ARRAY_LENGTH(AESBITS); ++bi) { + const int aesbits = AESBITS[bi]; + + for (int i = 0; i < 16; ++i) { + crypto_rand((char*)key, sizeof(key)); + crypto_rand((char*)tweak_h, sizeof(tweak_h)); + crypto_rand((char*)tweak_x_r, sizeof(tweak_x_r)); + crypto_rand((char*)block_orig, sizeof(block_orig)); + memcpy(block, block_orig, 16); + cgo_et_init(&et1, aesbits, true, key); + cgo_et_init(&et2, aesbits, false, key); + + // encrypt-then-decrypt should round-trip. + cgo_et_encrypt(&et1, tweak, block); + tt_mem_op(block, OP_NE, block_orig, 16); + cgo_et_decrypt(&et2, tweak, block); + tt_mem_op(block, OP_EQ, block_orig, 16); + + // decrypt-then-encrypt should round-trip. + cgo_et_decrypt(&et2, tweak, block); + tt_mem_op(block, OP_NE, block_orig, 16); + cgo_et_encrypt(&et1, tweak, block); + tt_mem_op(block, OP_EQ, block_orig, 16); + + cgo_et_clear(&et1); + cgo_et_clear(&et2); + } + } + done: + cgo_et_clear(&et1); + cgo_et_clear(&et2); +} + +static void +test_crypto_cgo_uiv_roundtrip(void *arg) +{ + (void)arg; + uint8_t key[64 + 32]; // max + uint8_t tweak_h[16]; + uint8_t cell[509], cell_orig[509]; + cgo_uiv_t uiv1, uiv2; + memset(&uiv1, 0, sizeof(uiv1)); + memset(&uiv2, 0, sizeof(uiv2)); + + uiv_tweak_t tweak = { + .h = tweak_h, + .cmd = 4, + }; + + for (int bi = 0; bi < (int) ARRAY_LENGTH(AESBITS); ++bi) { + const int aesbits = AESBITS[bi]; + + for (int i = 0; i < 16; ++i) { + crypto_rand((char*)key, sizeof(key)); + crypto_rand((char*)tweak_h, sizeof(tweak_h)); + crypto_rand((char*)cell_orig, sizeof(cell_orig)); + memcpy(cell, cell_orig, sizeof(cell_orig)); + + cgo_uiv_init(&uiv1, aesbits, true, key); + cgo_uiv_init(&uiv2, aesbits, false, key); + + // encrypt-then-decrypt should round-trip. + cgo_uiv_encrypt(&uiv1, tweak, cell); + tt_mem_op(cell, OP_NE, cell_orig, sizeof(cell)); + cgo_uiv_decrypt(&uiv2, tweak, cell); + tt_mem_op(cell, OP_EQ, cell_orig, sizeof(cell)); + + // decrypt-then-encrypt should round-trip. + cgo_uiv_decrypt(&uiv2, tweak, cell); + tt_mem_op(cell, OP_NE, cell_orig, sizeof(cell)); + cgo_uiv_encrypt(&uiv1, tweak, cell); + tt_mem_op(cell, OP_EQ, cell_orig, sizeof(cell)); + + cgo_uiv_clear(&uiv1); + cgo_uiv_clear(&uiv2); + } + } + done: + cgo_uiv_clear(&uiv1); + cgo_uiv_clear(&uiv2); +} + +#define UNHEX(out,inp) STMT_BEGIN { \ + size_t inplen = strlen(inp); \ + tt_int_op(sizeof(out), OP_EQ, inplen / 2); \ + int r = base16_decode((char*)(out), sizeof(out), inp, inplen); \ + tt_int_op(r, OP_EQ, sizeof(out)); \ + } STMT_END + +#define UNHEX2(out,inp1,inp2) STMT_BEGIN { \ + tor_free(unhex_tmp); \ + tor_asprintf(&unhex_tmp, "%s%s", inp1, inp2); \ + UNHEX(out, unhex_tmp); \ + } STMT_END + +static void +test_crypto_cgo_et_testvec(void *arg) +{ + (void)arg; + cgo_et_t et; + memset(&et, 0, sizeof(et)); + + for (int i = 0; i < (int)ARRAY_LENGTH(ET_TESTVECS); ++i) { + const struct et_testvec *tv = &ET_TESTVECS[i]; + uint8_t keys[32]; + uint8_t tweaks[16 + 1 + 493]; + uint8_t block[16], expect[16]; + UNHEX(keys, tv->keys); + UNHEX(tweaks, tv->tweaks); + UNHEX(block, tv->block); + UNHEX(expect, tv->expect); + + et_tweak_t tweak = { + .uiv = { + .h = tweaks, + .cmd = tweaks[16], + }, + .x_r = tweaks + 17, + }; + + cgo_et_init(&et, 128, tv->encrypt, keys); + if (tv->encrypt) { + cgo_et_encrypt(&et, tweak, block); + } else { + cgo_et_decrypt(&et, tweak, block); + } + cgo_et_clear(&et); + + tt_mem_op(block, OP_EQ, expect, 16); + } + + done: + cgo_et_clear(&et); +} + +static void +test_crypto_cgo_prf_testvec(void *arg) +{ + (void)arg; + cgo_prf_t prf; + memset(&prf, 0, sizeof(prf)); + + for (int i = 0; i < (int)ARRAY_LENGTH(PRF_TESTVECS); ++i) { + const struct prf_testvec *tv = &PRF_TESTVECS[i]; + uint8_t keys[32]; + uint8_t input[16]; + uint8_t expect_t0[493]; + uint8_t expect_t1[80]; + uint8_t output[493]; // max + UNHEX(keys, tv->keys); + UNHEX(input, tv->input); + + cgo_prf_init(&prf, 128, keys); + if (tv->t == 0) { + UNHEX(expect_t0, tv->expect); + memset(output, 0, sizeof(output)); + cgo_prf_xor_t0(&prf, input, output); + tt_mem_op(output, OP_EQ, expect_t0, PRF_T0_DATA_LEN); + } else { + tt_int_op(tv->t, OP_EQ, 1); + UNHEX(expect_t1, tv->expect); + cgo_prf_gen_t1(&prf, input, output, sizeof(expect_t1)); + tt_mem_op(output, OP_EQ, expect_t1, sizeof(expect_t1)); + } + cgo_prf_clear(&prf); + } + done: + cgo_prf_clear(&prf); +} + +static void +test_crypto_cgo_uiv_testvec(void *arg) +{ + (void)arg; + cgo_uiv_t uiv; + memset(&uiv, 0, sizeof(uiv)); + + for (int i = 0; i < (int)ARRAY_LENGTH(UIV_TESTVECS); ++i) { + const struct uiv_testvec *tv = &UIV_TESTVECS[i]; + uint8_t keys[64]; + uint8_t tweaks[17]; + uint8_t x_l[16], x_r[493]; + uint8_t y_l[16], y_r[493]; + uint8_t cell[509]; + UNHEX(keys, tv->keys); + UNHEX(tweaks, tv->tweaks); + UNHEX(x_l, tv->x_l); + UNHEX(x_r, tv->x_r); + UNHEX(y_l, tv->y.y_l); + UNHEX(y_r, tv->y.y_r); + + uiv_tweak_t tweak = { + .h = tweaks, + .cmd = tweaks[16] + }; + memcpy(cell, x_l, 16); + memcpy(cell+16, x_r, 493); + + cgo_uiv_init(&uiv, 128, tv->encrypt, keys); + if (tv->encrypt) { + cgo_uiv_encrypt(&uiv, tweak, cell); + } else { + cgo_uiv_decrypt(&uiv, tweak, cell); + } + cgo_uiv_clear(&uiv); + + tt_mem_op(cell, OP_EQ, y_l, 16); + tt_mem_op(cell+16, OP_EQ, y_r, 493); + } + + done: + cgo_uiv_clear(&uiv); +} + +#include "core/crypto/relay_crypto_st.h" + +static void +test_crypto_cgo_uiv_update_testvec(void *arg) +{ + (void)arg; + cgo_uiv_t uiv; + cgo_uiv_t uiv2; + memset(&uiv, 0, sizeof(uiv)); + memset(&uiv2, 0, sizeof(uiv2)); + + uint8_t tw[16]; + memset(tw, 42, sizeof(tw)); + uiv_tweak_t tweak = { + .h = tw, + .cmd = 42 + }; + + for (int i = 0; i < (int)ARRAY_LENGTH(UIV_UPDATE_TESTVECS); ++i) { + const struct uiv_update_testvec *tv = &UIV_UPDATE_TESTVECS[i]; + uint8_t keys[64]; + uint8_t nonce[16]; + uint8_t new_keys[64]; + uint8_t new_nonce[16]; + UNHEX(keys, tv->keys); + UNHEX(nonce, tv->nonce); + UNHEX(new_keys, tv->output.new_keys); + UNHEX(new_nonce, tv->output.new_nonce); + + cgo_uiv_init(&uiv, 128, true, keys); + cgo_uiv_update(&uiv, 128, true, nonce); + // Make sure that the recorded keys are what we expect. + tt_mem_op(uiv.uiv_keys_, OP_EQ, new_keys, 64); + tt_mem_op(nonce, OP_EQ, new_nonce, 16); + + // Construct a new UIV from these keys and make sure it acts like this one. + uint8_t cell[509], cell2[509]; + crypto_rand((char*)cell, sizeof(cell)); + memcpy(cell2, cell, 509); + cgo_uiv_init(&uiv2, 128, true, uiv.uiv_keys_); + cgo_uiv_encrypt(&uiv, tweak, cell); + cgo_uiv_encrypt(&uiv2, tweak, cell2); + tt_mem_op(cell, OP_EQ, cell2, 509); + + cgo_uiv_clear(&uiv); + cgo_uiv_clear(&uiv2); + } + done: + cgo_uiv_clear(&uiv); + cgo_uiv_clear(&uiv2); +} + +static void +test_crypto_cgo_fwd(void *arg) +{ + (void)arg; + + #define N_HOPS 3 + uint8_t key_material[N_HOPS][112]; // max. + cgo_crypt_t *client[N_HOPS]; + cgo_crypt_t *relays[N_HOPS]; + + memset(client, 0, sizeof(client)); + memset(relays, 0, sizeof(relays)); + + for (int bi = 0; bi < (int) ARRAY_LENGTH(AESBITS); ++bi) { + const int aesbits = AESBITS[bi]; + + size_t klen = cgo_key_material_len(aesbits); + tt_uint_op(klen, OP_LE, sizeof(key_material[0])); + crypto_rand((char*)&key_material, sizeof(key_material)); + for (int i = 0; i < N_HOPS; ++i) { + client[i] = cgo_crypt_new(CGO_MODE_CLIENT_FORWARD, + aesbits, key_material[i], klen); + relays[i] = cgo_crypt_new(CGO_MODE_RELAY_FORWARD, + aesbits, key_material[i], klen); + } + for (int trial = 0; trial < 64; ++trial) { + int target_hop = crypto_rand_int(3); + cell_t cell, cell_orig; + uint8_t tag_client[SENDME_TAG_LEN_CGO]; + const uint8_t *tagp = NULL; + + memset(&cell, 0, sizeof(cell)); + if (crypto_rand_int(2) == 0) { + cell.command = CELL_RELAY; + } else { + cell.command = CELL_RELAY_EARLY; + } + crypto_rand((char*) cell.payload+SENDME_TAG_LEN_CGO, + sizeof(cell.payload)-SENDME_TAG_LEN_CGO); + memcpy(&cell_orig, &cell, sizeof(cell)); + + // First the client encrypts the cell... + cgo_crypt_client_originate(client[target_hop], &cell, &tagp); + tt_assert(tagp); + memcpy(tag_client, tagp, SENDME_TAG_LEN_CGO); + for (int i = target_hop - 1; i >= 0; --i) { + cgo_crypt_client_forward(client[i], &cell); + } + + // Now the relays handle the cell... + bool cell_recognized = false; + for (int i = 0; i < N_HOPS; ++i) { + tagp = NULL; + cgo_crypt_relay_forward(relays[i], &cell, &tagp); + if (tagp) { + tt_int_op(i, OP_EQ, target_hop); + tt_mem_op(tagp, OP_EQ, tag_client, SENDME_TAG_LEN_CGO); + cell_recognized = true; + break; + } + } + tt_assert(cell_recognized); + tt_int_op(cell.command, OP_EQ, cell_orig.command); + tt_mem_op(cell.payload + SENDME_TAG_LEN_CGO, OP_EQ, + cell_orig.payload + SENDME_TAG_LEN_CGO, + sizeof(cell.payload) - SENDME_TAG_LEN_CGO); + } + for (int i = 0; i < N_HOPS; ++i) { + cgo_crypt_free(client[i]); + cgo_crypt_free(relays[i]); + } + } + + done: + for (int i = 0; i < N_HOPS; ++i) { + cgo_crypt_free(client[i]); + cgo_crypt_free(relays[i]); + } +#undef N_HOPS +} + +static void +test_crypto_cgo_rev(void *arg) +{ + (void)arg; + + #define N_HOPS 3 + uint8_t key_material[N_HOPS][112]; // max. + cgo_crypt_t *client[N_HOPS]; + cgo_crypt_t *relays[N_HOPS]; + + memset(client, 0, sizeof(client)); + memset(relays, 0, sizeof(relays)); + + for (int bi = 0; bi < (int) ARRAY_LENGTH(AESBITS); ++bi) { + const int aesbits = AESBITS[bi]; + + size_t klen = cgo_key_material_len(aesbits); + tt_uint_op(klen, OP_LE, sizeof(key_material[0])); + crypto_rand((char*)&key_material, sizeof(key_material)); + for (int i = 0; i < N_HOPS; ++i) { + client[i] = cgo_crypt_new(CGO_MODE_CLIENT_BACKWARD, + aesbits, key_material[i], klen); + relays[i] = cgo_crypt_new(CGO_MODE_RELAY_BACKWARD, + aesbits, key_material[i], klen); + } + for (int trial = 0; trial < 64; ++trial) { + int origin_hop = crypto_rand_int(3); + cell_t cell, cell_orig; + uint8_t tag_relay[SENDME_TAG_LEN_CGO]; + const uint8_t *tagp = NULL; + + memset(&cell, 0, sizeof(cell)); + cell.command = CELL_RELAY; + crypto_rand((char*) cell.payload+SENDME_TAG_LEN_CGO, + sizeof(cell.payload)-SENDME_TAG_LEN_CGO); + memcpy(&cell_orig, &cell, sizeof(cell)); + + // First the specified relay encrypts the cell... + cgo_crypt_relay_originate(relays[origin_hop], &cell, &tagp); + tt_assert(tagp); + memcpy(tag_relay, tagp, SENDME_TAG_LEN_CGO); + for (int i = origin_hop - 1; i >= 0; --i) { + cgo_crypt_relay_backward(relays[i], &cell); + } + + // Now the client handles the cell. + bool cell_recognized = false; + for (int i = 0; i < N_HOPS; ++i) { + tagp = NULL; + cgo_crypt_client_backward(client[i], &cell, &tagp); + if (tagp) { + tt_int_op(i, OP_EQ, origin_hop); + tt_mem_op(tagp, OP_EQ, tag_relay, SENDME_TAG_LEN_CGO); + cell_recognized = true; + break; + } + } + tt_assert(cell_recognized); + tt_int_op(cell.command, OP_EQ, cell_orig.command); + tt_mem_op(cell.payload + SENDME_TAG_LEN_CGO, OP_EQ, + cell_orig.payload + SENDME_TAG_LEN_CGO, + sizeof(cell.payload) - SENDME_TAG_LEN_CGO); + } + for (int i = 0; i < N_HOPS; ++i) { + cgo_crypt_free(client[i]); + cgo_crypt_free(relays[i]); + } + } + + done: + for (int i = 0; i < N_HOPS; ++i) { + cgo_crypt_free(client[i]); + cgo_crypt_free(relays[i]); + } +#undef N_HOPS +} + +static void +test_crypto_cgo_relay_testvec(void *arg) +{ + (void)arg; + char *unhex_tmp = NULL; + cgo_crypt_t *cgo = NULL; + for (int i = 0; i < (int)ARRAY_LENGTH(CGO_RELAY_TESTVECS); ++i) { + const struct cgo_relay_testvec *tv = &CGO_RELAY_TESTVECS[i]; + const int aesbits = 128; + uint8_t keys[80], expect_keys[80], expect_tprime[SENDME_TAG_LEN_CGO], + cmd[1]; + cell_t cell; + cell_t expect_cell; + tt_int_op(sizeof(keys), OP_EQ, cgo_key_material_len(aesbits)); + UNHEX2(keys, tv->state_in.keys, tv->state_in.nonce); + cgo_mode_t mode = + tv->inbound ? CGO_MODE_RELAY_BACKWARD : CGO_MODE_RELAY_FORWARD; + cgo = cgo_crypt_new(mode, aesbits, keys, sizeof(keys)); + tt_assert(cgo); + UNHEX(cgo->tprime, tv->state_in.tprime); + memset(&cell, 0, sizeof(cell)); + UNHEX(cmd, tv->cmd); + cell.command = cmd[0]; + UNHEX2(cell.payload, tv->tag, tv->msg); + + memset(&expect_cell, 0, sizeof(expect_cell)); + expect_cell.command = cell.command; + UNHEX2(expect_cell.payload, + tv->output.result.t_out, tv->output.result.msg_out); + UNHEX2(expect_keys, + tv->output.state.keys, tv->output.state.nonce); + UNHEX(expect_tprime, tv->output.state.tprime); + + if (tv->inbound) { + cgo_crypt_relay_backward(cgo, &cell); + } else { + const uint8_t *tagp = NULL; + cgo_crypt_relay_forward(cgo, &cell, &tagp); + tt_ptr_op(tagp, OP_EQ, NULL); + } + + tt_mem_op(cell.payload, OP_EQ, expect_cell.payload, sizeof(cell.payload)); + tt_mem_op(cgo->uiv.uiv_keys_, OP_EQ, expect_keys, 64); + tt_mem_op(cgo->nonce, OP_EQ, expect_keys + 64, 16); + tt_mem_op(cgo->tprime, OP_EQ, expect_tprime, 16); + + cgo_crypt_free(cgo); + } + done: + tor_free(unhex_tmp); + cgo_crypt_free(cgo); +} + +static void +test_crypto_cgo_relay_originate_testvec(void *arg) +{ + (void)arg; + char *unhex_tmp = NULL; + cgo_crypt_t *cgo = NULL; + for (int i = 0; i < (int)ARRAY_LENGTH(CGO_RELAY_ORIGINATE_TESTVECS); ++i) { + const struct cgo_relay_originate_testvec *tv = + &CGO_RELAY_ORIGINATE_TESTVECS[i]; + const int aesbits = 128; + uint8_t keys[80], expect_keys[80], expect_tprime[SENDME_TAG_LEN_CGO], + cmd[1]; + cell_t cell; + cell_t expect_cell; + tt_int_op(sizeof(keys), OP_EQ, cgo_key_material_len(aesbits)); + UNHEX2(keys, tv->state_in.keys, tv->state_in.nonce); + cgo = cgo_crypt_new(CGO_MODE_RELAY_BACKWARD, aesbits, keys, sizeof(keys)); + tt_assert(cgo); + UNHEX(cgo->tprime, tv->state_in.tprime); + memset(&cell, 0, sizeof(cell)); + UNHEX(cmd, tv->cmd); + cell.command = cmd[0]; + UNHEX2(cell.payload, "00000000000000000000000000000000", tv->msg); + + memset(&expect_cell, 0, sizeof(expect_cell)); + expect_cell.command = cell.command; + UNHEX2(expect_cell.payload, + tv->output.result.t_out, tv->output.result.msg_out); + UNHEX2(expect_keys, + tv->output.state.keys, tv->output.state.nonce); + UNHEX(expect_tprime, tv->output.state.tprime); + + const uint8_t *tagp = NULL; + cgo_crypt_relay_originate(cgo, &cell, &tagp); + tt_ptr_op(tagp, OP_NE, NULL); + + tt_mem_op(cell.payload, OP_EQ, expect_cell.payload, sizeof(cell.payload)); + tt_mem_op(cgo->uiv.uiv_keys_, OP_EQ, expect_keys, 64); + tt_mem_op(cgo->nonce, OP_EQ, expect_keys + 64, 16); + tt_mem_op(cgo->tprime, OP_EQ, expect_tprime, 16); + + cgo_crypt_free(cgo); + } + done: + tor_free(unhex_tmp); + cgo_crypt_free(cgo); +} + +static void +test_crypto_cgo_client_originate_testvec(void *arg) +{ + (void) arg; + char *unhex_tmp = NULL; + cgo_crypt_t *cgo[3] = { NULL, NULL, NULL }; + for (int tv_i = 0; tv_i < (int)ARRAY_LENGTH(CGO_CLIENT_ORIGINATE_TESTVECS); + ++tv_i) { + const struct cgo_client_originate_testvec *tv = + &CGO_CLIENT_ORIGINATE_TESTVECS[tv_i]; + const int aesbits = 128; + uint8_t keys[80], expect_keys[80], expect_tprime[SENDME_TAG_LEN_CGO], + cmd[1]; + cell_t cell; + cell_t expect_cell; + for (int i = 0; i < 3; ++i) { + tt_int_op(sizeof(keys), OP_EQ, cgo_key_material_len(aesbits)); + UNHEX2(keys, tv->state_in[i].keys, tv->state_in[i].nonce); + cgo[i] = cgo_crypt_new(CGO_MODE_CLIENT_FORWARD, + aesbits, keys, sizeof(keys)); + tt_assert(cgo[i]); + UNHEX(cgo[i]->tprime, tv->state_in[i].tprime); + } + + memset(&cell, 0, sizeof(cell)); + UNHEX(cmd, tv->cmd); + cell.command = cmd[0]; + UNHEX2(cell.payload, "00000000000000000000000000000000", tv->msg); + + memset(&expect_cell, 0, sizeof(expect_cell)); + expect_cell.command = cell.command; + UNHEX2(expect_cell.payload, + tv->output.result.t_out, tv->output.result.msg_out); + + tt_int_op(tv->target_hop, OP_GE, 1); // Hop is 0-indexed. + int target_hop = tv->target_hop - 1; + const uint8_t *tagp = NULL; + cgo_crypt_client_originate(cgo[target_hop], &cell, &tagp); + tt_ptr_op(tagp, OP_NE, NULL); + for (int i = target_hop - 1; i >= 0; --i) { + cgo_crypt_client_forward(cgo[i], &cell); + } + tt_mem_op(cell.payload, OP_EQ, expect_cell.payload, sizeof(cell.payload)); + + for (int i = 0; i < 3; ++i) { + UNHEX2(expect_keys, + tv->output.state[i].keys, tv->output.state[i].nonce); + UNHEX(expect_tprime, tv->output.state[i].tprime); + + tt_mem_op(cgo[i]->uiv.uiv_keys_, OP_EQ, expect_keys, 64); + tt_mem_op(cgo[i]->nonce, OP_EQ, expect_keys + 64, 16); + tt_mem_op(cgo[i]->tprime, OP_EQ, expect_tprime, 16); + } + + for (int i = 0; i < 3; ++i) + cgo_crypt_free(cgo[i]); + } + done: + tor_free(unhex_tmp); + for (int i = 0; i < 3; ++i) + cgo_crypt_free(cgo[i]); +} + +struct testcase_t crypto_cgo_tests[] = { + { "et_roundtrip", test_crypto_cgo_et_roundtrip, 0, NULL, NULL }, + { "et_testvec", test_crypto_cgo_et_testvec, 0, NULL, NULL }, + { "prf_testvec", test_crypto_cgo_prf_testvec, 0, NULL, NULL }, + { "uiv_roundtrip", test_crypto_cgo_uiv_roundtrip, 0, NULL, NULL }, + { "uiv_testvec", test_crypto_cgo_uiv_testvec, 0, NULL, NULL }, + { "uiv_update_testvec", test_crypto_cgo_uiv_update_testvec, 0, NULL, NULL }, + { "cgo_fwd", test_crypto_cgo_fwd, 0, NULL, NULL, }, + { "cgo_rev", test_crypto_cgo_rev, 0, NULL, NULL, }, + { "cgo_relay_testvec", test_crypto_cgo_relay_testvec, 0, NULL, NULL }, + { "cgo_relay_originate_testvec", test_crypto_cgo_relay_originate_testvec, + 0, NULL, NULL }, + { "cgo_client_originate_testvec", test_crypto_cgo_client_originate_testvec, + 0, NULL, NULL }, + END_OF_TESTCASES +}; diff -Nru tor-0.4.8.16/src/test/test_crypto_ope.c tor-0.4.9.6/src/test/test_crypto_ope.c --- tor-0.4.8.16/src/test/test_crypto_ope.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_crypto_ope.c 2026-03-25 14:30:34.000000000 +0000 @@ -28,7 +28,7 @@ const int TEST_VALS[] = { 5, 500, 1023, 1024, 1025, 2046, 2047, 2048, 2049, 10000, OPE_INPUT_MAX }; unsigned i; - const uint8_t key[32] = "A fixed key, chosen arbitrarily."; + NONSTRING const uint8_t key[32] = "A fixed key, chosen arbitrarily."; ope = crypto_ope_new(key); tt_assert(ope); @@ -56,7 +56,7 @@ (void)arg; crypto_ope_t *ope = NULL; - const uint8_t key[32] = "A fixed key, chosen arbitrarily."; + NONSTRING const uint8_t key[32] = "A fixed key, chosen arbitrarily."; ope = crypto_ope_new(key); tt_u64_op(UINT64_MAX, OP_EQ, crypto_ope_encrypt(ope,INT_MIN)); diff -Nru tor-0.4.8.16/src/test/test_crypto_openssl.c tor-0.4.9.6/src/test/test_crypto_openssl.c --- tor-0.4.8.16/src/test/test_crypto_openssl.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_crypto_openssl.c 2026-03-25 14:30:34.000000000 +0000 @@ -49,11 +49,6 @@ ; } -#ifndef OPENSSL_1_1_API -#define EVP_ENCODE_CTX_new() tor_malloc_zero(sizeof(EVP_ENCODE_CTX)) -#define EVP_ENCODE_CTX_free(ctx) tor_free(ctx) -#endif - /** Encode src into dest with OpenSSL's EVP Encode interface, returning the * length of the encoded data in bytes. */ diff -Nru tor-0.4.8.16/src/test/test_dir.c tor-0.4.9.6/src/test/test_dir.c --- tor-0.4.8.16/src/test/test_dir.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_dir.c 2026-03-25 14:30:34.000000000 +0000 @@ -21,6 +21,8 @@ #define RELAY_PRIVATE #define ROUTERLIST_PRIVATE #define ROUTER_PRIVATE +#define ROUTERKEYS_PRIVATE +#define ROUTERPARSE_PRIVATE #define UNPARSEABLE_PRIVATE #define VOTEFLAGS_PRIVATE @@ -217,7 +219,7 @@ r1->ipv4_dirport = dir_port; r1->supports_tunnelled_dir_requests = 1; - router_set_rsa_onion_pkey(pk1, &r1->onion_pkey, &r1->onion_pkey_len); + router_set_rsa_onion_pkey(pk1, &r1->tap_onion_pkey, &r1->tap_onion_pkey_len); r1->identity_pkey = pk2; r1->bandwidthrate = bandwidthrate; @@ -382,8 +384,8 @@ { char *block = NULL; tor_assert(r1); - crypto_pk_t *pk_tmp = router_get_rsa_onion_pkey(r1->onion_pkey, - r1->onion_pkey_len); + crypto_pk_t *pk_tmp = router_get_rsa_onion_pkey(r1->tap_onion_pkey, + r1->tap_onion_pkey_len); block = get_new_rsa_key_block("onion-key", pk_tmp); crypto_pk_free(pk_tmp); return block; @@ -587,8 +589,8 @@ if (rsa_onion_keypair) { mocked_onionkey = crypto_pk_dup_key(rsa_onion_keypair); } else { - mocked_onionkey = router_get_rsa_onion_pkey(r1->onion_pkey, - r1->onion_pkey_len); + mocked_onionkey = router_get_rsa_onion_pkey(r1->tap_onion_pkey, + r1->tap_onion_pkey_len); } MOCK(get_onion_key, mock_get_onion_key); } @@ -643,10 +645,12 @@ tt_int_op(rp1->bandwidthrate,OP_EQ, r1->bandwidthrate); \ tt_int_op(rp1->bandwidthburst,OP_EQ, r1->bandwidthburst); \ tt_int_op(rp1->bandwidthcapacity,OP_EQ, r1->bandwidthcapacity); \ - crypto_pk_t *rp1_onion_pkey = router_get_rsa_onion_pkey(rp1->onion_pkey, \ - rp1->onion_pkey_len); \ - crypto_pk_t *r1_onion_pkey = router_get_rsa_onion_pkey(r1->onion_pkey, \ - r1->onion_pkey_len); \ + crypto_pk_t *rp1_onion_pkey = router_get_rsa_onion_pkey( \ + rp1->tap_onion_pkey, \ + rp1->tap_onion_pkey_len); \ + crypto_pk_t *r1_onion_pkey = router_get_rsa_onion_pkey( \ + r1->tap_onion_pkey, \ + r1->tap_onion_pkey_len); \ tt_int_op(crypto_pk_cmp_keys(rp1_onion_pkey, r1_onion_pkey), OP_EQ, 0); \ crypto_pk_free(rp1_onion_pkey); \ crypto_pk_free(r1_onion_pkey); \ @@ -862,8 +866,21 @@ tt_str_op(buf, OP_EQ, buf2); tor_free(buf); + /* We make a couple of changes now before we make the desc that we're going + * to parse and check the signature on. */ setup_mock_configured_ports(r2->ipv4_orport, 0); + ed25519_keypair_t family_1; + ed25519_keypair_t family_2; + ed25519_keypair_generate(&family_1, 0); + ed25519_keypair_generate(&family_2, 0); + { + smartlist_t *family_keys = smartlist_new(); + smartlist_add(family_keys, tor_memdup(&family_1, sizeof(family_1))); + smartlist_add(family_keys, tor_memdup(&family_2, sizeof(family_2))); + set_family_id_keys(family_keys); // takes ownership. + } + buf = router_dump_router_to_string(r2, r2->identity_pkey, r2_onion_pkey, &r2_onion_keypair, &kp2); @@ -881,6 +898,20 @@ r2->onion_curve25519_pkey->public_key, CURVE25519_PUBKEY_LEN); + // Check family ids. + tt_assert(rp2->family_ids != NULL); + tt_int_op(smartlist_len(rp2->family_ids), OP_EQ, 2); + { + char k[ED25519_BASE64_LEN+1]; + char b[sizeof(k)+16]; + ed25519_public_to_base64(k, &family_1.pubkey); + tor_snprintf(b, sizeof(b), "ed25519:%s", k); + tt_assert(smartlist_contains_string(rp2->family_ids, b)); + ed25519_public_to_base64(k, &family_2.pubkey); + tor_snprintf(b, sizeof(b), "ed25519:%s", k); + tt_assert(smartlist_contains_string(rp2->family_ids, b)); + } + CHECK_PARSED_EXIT_POLICY(rp2); tor_free(buf); @@ -1303,6 +1334,72 @@ #undef ADD } +/* Made with chutney and a patched tor: Has no onion-key or + * onion-key-crosscert */ +static const char ROUTERDESC_NO_ONION_KEY[] = +"router test001a 127.0.0.1 5001 0 7001\n" +"identity-ed25519\n" +"-----BEGIN ED25519 CERT-----\n" +"AQQAB0xWARbCJfDrX0OTtpM0fDxU9cLweMnZeUq/KBfAN1wwWHtMAQAgBADBQJ1o\n" +"ClrXUenWC90FYEUQDpMSdxdxKlrR83rYy+keGe61WQHYP0ebowJC19UvPnYryLeA\n" +"Gnhko2WwmbUDGicdnY4j2VSFU15oxBjln65IznZJyiZM4zGE1GkNZzKGmQY=\n" +"-----END ED25519 CERT-----\n" +"master-key-ed25519 wUCdaApa11Hp1gvdBWBFEA6TEncXcSpa0fN62MvpHhk\n" +"or-address [::]:5001\n" +"platform Tor 0.4.9.0-alpha-dev on Linux\n" +"proto Conflux=1 Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1-2 HSDir=2 " + "HSIntro=4-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 " + "Relay=1-4\n" +"published 2024-06-24 21:34:22\n" +"fingerprint FD3A 6FA4 E716 C379 3CBA FEC3 39EA 01C8 B49D 7189\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest 9946CAC41485EDFFDD83F7DAF1A088C30563126C " + "lpAMRlRTy9QR2xVCu1nnnxOHA2I05TTKvCSPPcr1geo\n" +"caches-extra-info\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBALcIIij7gNpvSZPvaCLDDNyyQZq7fR0aXiHgmiIc5hYVcBl+zF5sTX6a\n" +"jQF+GQdbSHcRzA1IMWPXnA7+nGOxSNayrQwExuf7ESsBaQHU81/dmV+rgTwtcd3K\n" +"9lobTQUm+idLvGjVF5P1XJkduPvURIgpIfXT1ZHJUQhwxWSw8MmnAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"ntor-onion-key-crosscert 1\n" +"-----BEGIN ED25519 CERT-----\n" +"AQoAB0wmAcFAnWgKWtdR6dYL3QVgRRAOkxJ3F3EqWtHzetjL6R4ZAFPSCMLyQ82v\n" +"dvcpZDa7C/qp8TsJn2Z8v77RjRc2QD1KYDzGfg5euwlB1lu8+IR38l3mmC1PXXhe\n" +"ZB84q4aUdAA=\n" +"-----END ED25519 CERT-----\n" +"hidden-service-dir\n" +"contact auth1@test.test\n" +"ntor-onion-key m0dedSB2vjtvz08bNu+LCdIApVuspRlzXbsphXZ62zQ\n" +"reject *:*\n" +"tunnelled-dir-server\n" +"router-sig-ed25519 VMwmiN9KhWWFSFSuVZxG1g46mb2QhMhv0UlatvPKyAV+1jPl" + "EbDFaO1Qur0335Rn0ToysC6UqB1p78pefX67Aw\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"q9Hxy4FJVIK2ks/ByBv8P1p7Pc68ie/TTlDN+tce9opPlijy9+ze9/Gd2SKonRm1\n" +"J+WBj/kKYKw+YoUExIT0qMfa6QTCOe/ecp1sNmgeW0YfloP4Nv8goi3S0k4yrPk/\n" +"qw6TIXGYJpvrdR1Qe7+MEl2K1Okqsy5amtOU400lYRA=\n" +"-----END SIGNATURE-----\n" + ; + +static void +test_dir_parse_no_onion_keyrouter_list(void *arg) +{ + (void) arg; + + routerinfo_t *ri = + router_parse_entry_from_string(ROUTERDESC_NO_ONION_KEY, NULL, + 0, 1, 0, NULL); + + tt_assert(ri); + tt_assert(ri->tap_onion_pkey == NULL); + + done: + routerinfo_free(ri); +} + static download_status_t dls_minimal; static download_status_t dls_maximal; static download_status_t dls_bad_fingerprint; @@ -2544,7 +2641,7 @@ smartlist_len(bw_file_headers)); /* force bw_file_headers to be bigger than * MAX_BW_FILE_HEADER_COUNT_IN_VOTE */ - char line[8] = "foo=bar\0"; + NONSTRING char line[8] = "foo=bar\0"; smartlist_add_strdup(bw_file_headers, line); tt_int_op(MAX_BW_FILE_HEADER_COUNT_IN_VOTE, OP_LT, smartlist_len(bw_file_headers)); @@ -4079,7 +4176,7 @@ if (vrs) { vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t)); tor_asprintf(&vrs->microdesc->microdesc_hash_line, - "m 25,26,27,28 " + "m 32,33 " "sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n", idx); } @@ -4103,9 +4200,8 @@ tt_assert(v->supported_methods); SMARTLIST_FOREACH(v->supported_methods, char *, c, tor_free(c)); smartlist_clear(v->supported_methods); - /* Method 17 is MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB */ smartlist_split_string(v->supported_methods, - "25 26 27 28", + "32 33", NULL, 0, -1); /* If we're using a non-default clip bandwidth, add it to net_params */ if (alternate_clip_bw > 0) { @@ -4450,14 +4546,17 @@ char *fname = tor_strdup(get_fname("V3BandwidthsFile")); /* Initialize to a wrong digest. */ - uint8_t digest[DIGEST256_LEN] = "01234567890123456789abcdefghijkl"; + NONSTRING + uint8_t digest[DIGEST256_LEN] = "01234567890123456789abcdefghijkl"; /* Digest of an empty string. Initialize to a wrong digest. */ - char digest_empty_str[DIGEST256_LEN] = "01234567890123456789abcdefghijkl"; + NONSTRING + char digest_empty_str[DIGEST256_LEN] = "01234567890123456789abcdefghijkl"; crypto_digest256(digest_empty_str, "", 0, DIGEST_SHA256); /* Digest of the content. Initialize to a wrong digest. */ - char digest_expected[DIGEST256_LEN] = "01234567890123456789abcdefghijkl"; + NONSTRING + char digest_expected[DIGEST256_LEN] = "01234567890123456789abcdefghijkl"; crypto_digest256(digest_expected, content, strlen(content), DIGEST_SHA256); /* When the bandwidth file can not be found. */ @@ -7201,6 +7300,126 @@ crypto_pk_free(pk); } +static void +test_dir_parse_family_cert(void *arg) +{ + (void)arg; + ed25519_keypair_t kp_family; + ed25519_keypair_t kp_id; + char family_b64[ED25519_BASE64_LEN+1]; + tor_cert_t *cert = NULL; + int r; + + time_t now = 1739288377; + time_t lifetime = 86400; + time_t got_expiration = -1; + char *got_family_id = NULL; + char *expect_family_id = NULL; + + setup_capture_of_logs(LOG_WARN); + + ed25519_keypair_generate(&kp_family, 0); + ed25519_keypair_generate(&kp_id, 0); + ed25519_public_to_base64(family_b64, &kp_family.pubkey); + tor_asprintf(&expect_family_id, "ed25519:%s", family_b64); + + // Wrong type. + cert = tor_cert_create_ed25519(&kp_family, + CERT_TYPE_ID_SIGNING, + &kp_id.pubkey, + now, lifetime, + CERT_FLAG_INCLUDE_SIGNING_KEY); + tt_assert(cert); + r = check_one_family_cert(cert->encoded, cert->encoded_len, + &kp_id.pubkey, + &got_family_id, + &got_expiration); + tt_ptr_op(got_family_id, OP_EQ, NULL); + tt_int_op(r, OP_EQ, -1); + expect_single_log_msg_containing("Wrong cert type"); + mock_clean_saved_logs(); + tor_cert_free(cert); + + // Family key not included. + cert = tor_cert_create_ed25519(&kp_family, + CERT_TYPE_FAMILY_V_IDENTITY, + &kp_id.pubkey, + now, lifetime, + 0); + tt_assert(cert); + r = check_one_family_cert(cert->encoded, cert->encoded_len, + &kp_id.pubkey, + &got_family_id, + &got_expiration); + tt_ptr_op(got_family_id, OP_EQ, NULL); + tt_int_op(r, OP_EQ, -1); + expect_single_log_msg_containing("Missing family key"); + mock_clean_saved_logs(); + tor_cert_free(cert); + + // Certified key isn't correct + cert = tor_cert_create_ed25519(&kp_family, + CERT_TYPE_FAMILY_V_IDENTITY, + &kp_family.pubkey, + now, lifetime, + CERT_FLAG_INCLUDE_SIGNING_KEY); + tt_assert(cert); + r = check_one_family_cert(cert->encoded, cert->encoded_len, + &kp_id.pubkey, + &got_family_id, + &got_expiration); + tt_ptr_op(got_family_id, OP_EQ, NULL); + tt_int_op(r, OP_EQ, -1); + expect_single_log_msg_containing("Key mismatch"); + mock_clean_saved_logs(); + tor_cert_free(cert); + + // Signature is bogus. + cert = tor_cert_create_ed25519(&kp_family, + CERT_TYPE_FAMILY_V_IDENTITY, + &kp_id.pubkey, + now, lifetime, + CERT_FLAG_INCLUDE_SIGNING_KEY); + tt_assert(cert); + cert->encoded[cert->encoded_len-1] ^= 0x77; // corrupt the signature + r = check_one_family_cert(cert->encoded, cert->encoded_len, + &kp_id.pubkey, + &got_family_id, + &got_expiration); + tt_ptr_op(got_family_id, OP_EQ, NULL); + tt_int_op(r, OP_EQ, -1); + expect_single_log_msg_containing("Invalid signature"); + mock_clean_saved_logs(); + tor_cert_free(cert); + + // Everything is okay! + cert = tor_cert_create_ed25519(&kp_family, + CERT_TYPE_FAMILY_V_IDENTITY, + &kp_id.pubkey, + now, lifetime, + CERT_FLAG_INCLUDE_SIGNING_KEY); + tt_assert(cert); + got_expiration = -1; + r = check_one_family_cert(cert->encoded, cert->encoded_len, + &kp_id.pubkey, + &got_family_id, + &got_expiration); + expect_no_log_entry(); + tt_int_op(r, OP_EQ, 0); + tt_int_op(got_expiration, OP_NE, -1); + // Cert expirations have 1-hour granularity + tt_int_op(got_expiration, OP_GE, now + lifetime); + tt_int_op(got_expiration, OP_LT, now + lifetime + 3601); + tt_str_op(got_family_id, OP_EQ, expect_family_id); + tt_assert(!strchr(got_family_id, '=')); // not family + + done: + tor_cert_free(cert); + tor_free(got_family_id); + tor_free(expect_family_id); + teardown_capture_of_logs(); +} + #ifndef COCCI #define DIR_LEGACY(name) \ { #name, test_dir_ ## name , TT_FORK, NULL, NULL } @@ -7228,6 +7447,7 @@ DIR(routerinfo_parsing, 0), DIR(extrainfo_parsing, 0), DIR(parse_router_list, TT_FORK), + DIR(parse_no_onion_keyrouter_list, TT_FORK), DIR(load_routers, TT_FORK), DIR(load_extrainfo, TT_FORK), DIR(getinfo_extra, 0), @@ -7286,5 +7506,6 @@ DIR(dirserv_router_get_status, TT_FORK), DIR(dirserv_would_reject_router, TT_FORK), DIR(dirserv_add_own_fingerprint, TT_FORK), + DIR(parse_family_cert, TT_FORK), END_OF_TESTCASES }; diff -Nru tor-0.4.8.16/src/test/test_dirvote.c tor-0.4.9.6/src/test/test_dirvote.c --- tor-0.4.8.16/src/test/test_dirvote.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_dirvote.c 2026-03-25 14:30:34.000000000 +0000 @@ -656,30 +656,6 @@ ROUTER_FREE(pppp); } -static void -test_dirvote_parse_param_buggy(void *arg) -{ - (void)arg; - - /* Tests for behavior with bug emulation to migrate away from bug 19011. */ - tt_i64_op(extract_param_buggy("blah blah", "bwweightscale", 10000), - OP_EQ, 10000); - tt_i64_op(extract_param_buggy("bwweightscale=7", "bwweightscale", 10000), - OP_EQ, 7); - tt_i64_op(extract_param_buggy("bwweightscale=7 foo=9", - "bwweightscale", 10000), - OP_EQ, 10000); - tt_i64_op(extract_param_buggy("foo=7 bwweightscale=777 bar=9", - "bwweightscale", 10000), - OP_EQ, 10000); - tt_i64_op(extract_param_buggy("foo=7 bwweightscale=1234", - "bwweightscale", 10000), - OP_EQ, 1234); - - done: - ; -} - #define NODE(name, flags) \ { \ #name, test_dirvote_##name, (flags), NULL, NULL \ @@ -692,5 +668,4 @@ NODE(get_sybil_by_ip_version_ipv4, TT_FORK), NODE(get_sybil_by_ip_version_ipv6, TT_FORK), NODE(get_all_possible_sybil, TT_FORK), - NODE(parse_param_buggy, 0), END_OF_TESTCASES}; diff -Nru tor-0.4.8.16/src/test/test_entrynodes.c tor-0.4.9.6/src/test/test_entrynodes.c --- tor-0.4.8.16/src/test/test_entrynodes.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_entrynodes.c 2026-03-25 14:30:34.000000000 +0000 @@ -24,6 +24,7 @@ #include "feature/dirclient/dirclient.h" #include "feature/client/entrynodes.h" #include "feature/nodelist/nodelist.h" +#include "feature/nodelist/nodefamily.h" #include "feature/nodelist/networkstatus.h" #include "core/or/policies.h" #include "feature/nodelist/routerlist.h" @@ -1942,8 +1943,10 @@ tt_ptr_op(g2, OP_EQ, g); /* But if we impose a restriction, we don't get the same guard */ + get_options_mutable()->EnforceDistinctSubnets = 0; rst = guard_create_exit_restriction((uint8_t*)g->identity); g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, rst, &state); + tt_assert(g2); tt_ptr_op(g2, OP_NE, g); done: @@ -2323,6 +2326,75 @@ } static void +test_entry_guard_select_for_circuit_exit_family_restriction(void *arg) +{ + (void) arg; + entry_guard_restriction_t *rst = NULL; + entry_guard_restriction_t *rst2 = NULL; + guard_selection_t *gs = guard_selection_new("default", GS_TYPE_NORMAL); + int retval; + unsigned state = 9999; + + /* Create our circuit */ + circuit_t *circ = dummy_origin_circuit_new(30); + origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(circ); + oc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); + + /* First pick the exit and pin it on the build_state */ + retval = onion_pick_cpath_exit(oc, NULL); + tt_int_op(retval, OP_EQ, 0); + + /* Then pick a guard */ + entry_guards_update_primary(gs); + entry_guard_t *g = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, + NULL, &state); + + tt_assert(g); + tt_assert(g->is_primary); + tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); + tt_i64_op(g->last_tried_to_connect, OP_EQ, approx_time()); + + /* Add the guard and the exit to each others' families */ + get_options_mutable()->EnforceDistinctSubnets = 0; + const char* exit_id = + (const char*)build_state_get_exit_rsa_id(oc->build_state); + const node_t *exit = node_get_by_id(exit_id); + const node_t *guard = node_get_by_id(g->identity); + exit->md->family = nodefamily_parse((const char*)g->nickname, + node_get_rsa_id_digest(exit),0); + guard->md->family = + nodefamily_parse((const char*)exit->rs->nickname, + node_get_rsa_id_digest(guard),0); + tt_assert(nodefamily_contains_nickname(exit->md->family, + (const char*)g->nickname)); + + /* We should get a different guard, after adding the exit restriction */ + rst = guard_create_exit_restriction((const uint8_t*)exit_id); + entry_guard_t *g2 = + select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, rst, &state); + tt_assert(g2); + tt_assert(g2->is_primary); + tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); + tt_i64_op(g2->last_tried_to_connect, OP_EQ, approx_time()); + tt_ptr_op(g2, OP_NE, g); + + /* Now check that conflux circuits satisfy the exit family restriction */ + rst2 = guard_create_conflux_restriction(oc, (const uint8_t*)exit_id); + g2 = select_entry_guard_for_circuit(gs, GUARD_USAGE_TRAFFIC, rst2, &state); + tt_assert(g2); + tt_assert(g2->is_primary); + tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_ON_COMPLETION); + tt_i64_op(g2->last_tried_to_connect, OP_EQ, approx_time()); + tt_ptr_op(g2, OP_NE, g); + + done: + circuit_free_(circ); + guard_selection_free(gs); + entry_guard_restriction_free(rst); + entry_guard_restriction_free(rst2); +} + +static void test_entry_guard_select_and_cancel(void *arg) { (void) arg; @@ -3199,6 +3271,7 @@ BFN_TEST(select_for_circuit_highlevel_primary), BFN_TEST(select_for_circuit_highlevel_confirm_other), BFN_TEST(select_for_circuit_highlevel_primary_retry), + BFN_TEST(select_for_circuit_exit_family_restriction), BFN_TEST(select_and_cancel), BFN_TEST(drop_guards), BFN_TEST(outdated_dirserver_exclusion), diff -Nru tor-0.4.8.16/src/test/test_extorport.c tor-0.4.9.6/src/test/test_extorport.c --- tor-0.4.8.16/src/test/test_extorport.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_extorport.c 2026-03-25 14:30:34.000000000 +0000 @@ -166,7 +166,7 @@ size_t reply_len=0; char hmac1[32], hmac2[32]; - const char client_nonce[32] = + NONSTRING const char client_nonce[32] = "Who is the third who walks alway"; char server_hash_input[] = "ExtORPort authentication server-to-client hash" diff -Nru tor-0.4.8.16/src/test/test_geoip.c tor-0.4.9.6/src/test/test_geoip.c --- tor-0.4.8.16/src/test/test_geoip.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_geoip.c 2026-03-25 14:30:34.000000000 +0000 @@ -58,7 +58,8 @@ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" "dirreq-v3-ips ab=8\n" "dirreq-v3-reqs ab=8\n" - "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0," + "dirreq-v3-resp " + "served=0,ok=0,not-enough-sigs=0,unavailable=0,not-found=0," "not-modified=0,busy=0\n" "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n", @@ -66,7 +67,8 @@ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" "dirreq-v3-ips \n" "dirreq-v3-reqs \n" - "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0," + "dirreq-v3-resp " + "served=0,ok=0,not-enough-sigs=0,unavailable=0,not-found=0," "not-modified=0,busy=0\n" "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n", @@ -74,7 +76,8 @@ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" "dirreq-v3-ips \n" "dirreq-v3-reqs \n" - "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0," + "dirreq-v3-resp " + "served=8,ok=8,not-enough-sigs=0,unavailable=0,not-found=0," "not-modified=0,busy=0\n" "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n", @@ -82,7 +85,8 @@ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" "dirreq-v3-ips \n" "dirreq-v3-reqs \n" - "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0," + "dirreq-v3-resp " + "served=8,ok=8,not-enough-sigs=0,unavailable=0,not-found=0," "not-modified=0,busy=0\n" "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n", @@ -230,6 +234,7 @@ /* Note a successful network status response and make sure that it * appears in the history string. */ + geoip_note_ns_response(GEOIP_SERVED); geoip_note_ns_response(GEOIP_SUCCESS); s = geoip_format_dirreq_stats(now + 86400); tt_str_op(dirreq_stats_3,OP_EQ, s); diff -Nru tor-0.4.8.16/src/test/test_hs_client.c tor-0.4.9.6/src/test/test_hs_client.c --- tor-0.4.8.16/src/test/test_hs_client.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_hs_client.c 2026-03-25 14:30:34.000000000 +0000 @@ -246,12 +246,14 @@ tt_int_op(retval, OP_EQ, 1); /* Check that the crypt path has prop224 algorithm parameters */ - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest), + tt_int_op(crypto_digest_get_algorithm( + or_circ->cpath->pvt_crypto.c.tor1.f_digest), OP_EQ, DIGEST_SHA3_256); - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest), + tt_int_op(crypto_digest_get_algorithm( + or_circ->cpath->pvt_crypto.c.tor1.b_digest), OP_EQ, DIGEST_SHA3_256); - tt_assert(or_circ->cpath->pvt_crypto.f_crypto); - tt_assert(or_circ->cpath->pvt_crypto.b_crypto); + tt_assert(or_circ->cpath->pvt_crypto.c.tor1.f_crypto); + tt_assert(or_circ->cpath->pvt_crypto.c.tor1.b_crypto); /* Ensure that circ purpose was changed */ tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_C_REND_JOINED); @@ -1092,7 +1094,7 @@ char *desc_encoded = NULL; circuit_t *circ = NULL; origin_circuit_t *ocirc = NULL; - tor_addr_t addr; + tor_addr_t addr = TOR_ADDR_NULL; ed25519_keypair_t service_kp; ed25519_keypair_t signing_kp; entry_connection_t *socks_conn = NULL; @@ -1192,7 +1194,7 @@ ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); /* Code path will log this exit so build it. */ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest, - NULL, NULL, NULL, &addr, + NULL, NULL, &addr, 4242, NULL, false); /* Attach socks connection to this rendezvous circuit. */ ocirc->p_streams = ENTRY_TO_EDGE_CONN(socks_conn); @@ -1266,7 +1268,7 @@ circuit_t *circ = NULL; ed25519_keypair_t service_kp, intro_kp; origin_circuit_t *ocirc = NULL; - tor_addr_t addr; + tor_addr_t addr = TOR_ADDR_NULL; const hs_cache_intro_state_t *entry; (void) arg; @@ -1287,7 +1289,7 @@ ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); /* Code path will log this exit so build it. */ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest, - NULL, NULL, NULL, &addr, + NULL, NULL, &addr, 4242, NULL, false); ed25519_pubkey_copy(ô->hs_ident->intro_auth_pk, &intro_kp.pubkey); @@ -1314,7 +1316,7 @@ ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); /* Code path will log this exit so build it. */ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest, - NULL, NULL, NULL, &addr, + NULL, NULL, &addr, 4242, NULL, false); ed25519_pubkey_copy(ô->hs_ident->intro_auth_pk, &intro_kp.pubkey); @@ -1337,7 +1339,7 @@ ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); /* Code path will log this exit so build it. */ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest, - NULL, NULL, NULL, &addr, + NULL, NULL, &addr, 4242, NULL, false); ed25519_pubkey_copy(ô->hs_ident->intro_auth_pk, &intro_kp.pubkey); diff -Nru tor-0.4.8.16/src/test/test_hs_control.c tor-0.4.9.6/src/test/test_hs_control.c --- tor-0.4.8.16/src/test/test_hs_control.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_hs_control.c 2026-03-25 14:30:34.000000000 +0000 @@ -23,6 +23,7 @@ #include "app/config/config.h" #include "feature/hs/hs_common.h" #include "feature/hs/hs_client.h" +#include "feature/hs/hs_config.h" #include "feature/hs/hs_control.h" #include "feature/nodelist/nodelist.h" @@ -829,8 +830,12 @@ list_good = smartlist_new(); smartlist_add(list_good, client_good); - add_onion_helper_add_service(HS_VERSION_THREE, &sk_good, portcfgs, 1, 1, - list_good, &address_out_good); + add_onion_helper_add_service( + HS_VERSION_THREE, &sk_good, portcfgs, 1, 1, + /*pow_defenses_enabled=*/1, + /*pow_queue_rate=*/HS_CONFIG_V3_POW_QUEUE_RATE, + /*pow_queue_burst=*/HS_CONFIG_V3_POW_QUEUE_BURST, + list_good, &address_out_good); service_good = find_service(global_map, &pk_good); tt_int_op(smartlist_len(service_good->config.clients), OP_EQ, 1); @@ -845,8 +850,12 @@ portcfgs = smartlist_new(); smartlist_add(portcfgs, portcfg); - add_onion_helper_add_service(HS_VERSION_THREE, &sk_bad, portcfgs, 1, 1, - list_bad, &address_out_bad); + add_onion_helper_add_service( + HS_VERSION_THREE, &sk_bad, portcfgs, 1, 1, + /*pow_defenses_enabled=*/1, + /*pow_queue_rate=*/HS_CONFIG_V3_POW_QUEUE_RATE, + /*pow_queue_burst=*/HS_CONFIG_V3_POW_QUEUE_BURST, + list_bad, &address_out_bad); service_bad = find_service(global_map, &pk_bad); diff -Nru tor-0.4.8.16/src/test/test_hs_intropoint.c tor-0.4.9.6/src/test/test_hs_intropoint.c --- tor-0.4.8.16/src/test/test_hs_intropoint.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_hs_intropoint.c 2026-03-25 14:30:34.000000000 +0000 @@ -544,7 +544,7 @@ or_circuit_t *intro_circ = NULL; trn_cell_establish_intro_t *establish_intro_cell = NULL; - ed25519_public_key_t auth_key; + ed25519_public_key_t auth_key = {0}; or_circuit_t *returned_intro_circ = NULL; diff -Nru tor-0.4.8.16/src/test/test_hs_service.c tor-0.4.9.6/src/test/test_hs_service.c --- tor-0.4.8.16/src/test/test_hs_service.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_hs_service.c 2026-03-25 14:30:34.000000000 +0000 @@ -224,12 +224,14 @@ tt_int_op(retval, OP_EQ, 1); /* Check the digest algo */ - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest), + tt_int_op(crypto_digest_get_algorithm( + or_circ->cpath->pvt_crypto.c.tor1.f_digest), OP_EQ, DIGEST_SHA3_256); - tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest), + tt_int_op(crypto_digest_get_algorithm( + or_circ->cpath->pvt_crypto.c.tor1.b_digest), OP_EQ, DIGEST_SHA3_256); - tt_assert(or_circ->cpath->pvt_crypto.f_crypto); - tt_assert(or_circ->cpath->pvt_crypto.b_crypto); + tt_assert(or_circ->cpath->pvt_crypto.c.tor1.f_crypto); + tt_assert(or_circ->cpath->pvt_crypto.c.tor1.b_crypto); /* Ensure that circ purpose was changed */ tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED); @@ -1605,7 +1607,6 @@ tt_int_op(ret, OP_EQ, 0); ri.onion_curve25519_pkey = tor_malloc_zero(sizeof(curve25519_public_key_t)); - ri.onion_pkey = tor_malloc_zero(140); curve25519_public_key_generate(ri.onion_curve25519_pkey, &curve25519_secret_key); memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN); @@ -1631,7 +1632,6 @@ update_all_descriptors_intro_points(now); tor_free(node->ri->onion_curve25519_pkey); /* Avoid memleak. */ tor_free(node->ri->cache_info.signing_key_cert); - tor_free(node->ri->onion_pkey); expect_log_msg_containing("just picked 1 intro points and wanted 3 for next " "descriptor. It currently has 0 intro points. " "Launching ESTABLISH_INTRO circuit shortly."); diff -Nru tor-0.4.8.16/src/test/test_include.sh tor-0.4.9.6/src/test/test_include.sh --- tor-0.4.8.16/src/test/test_include.sh 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_include.sh 2026-03-25 14:30:34.000000000 +0000 @@ -50,7 +50,7 @@ tmpdir= # For some reasons, shellcheck is not seeing that we can call this # function from the trap below. -# shellcheck disable=SC2317 +# shellcheck disable=SC2317,SC2329 clean () { if [ -n "$tmpdir" ] && [ -d "$tmpdir" ]; then rm -rf "$tmpdir" diff -Nru tor-0.4.8.16/src/test/test_link_handshake.c tor-0.4.9.6/src/test/test_link_handshake.c --- tor-0.4.8.16/src/test/test_link_handshake.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_link_handshake.c 2026-03-25 14:30:34.000000000 +0000 @@ -943,25 +943,15 @@ cell1 = mock_got_var_cell; tt_int_op(0, OP_EQ, connection_or_send_auth_challenge_cell(c1)); cell2 = mock_got_var_cell; -#ifdef HAVE_WORKING_TOR_TLS_GET_TLSSECRETS - tt_int_op(38, OP_EQ, cell1->payload_len); - tt_int_op(38, OP_EQ, cell2->payload_len); -#else tt_int_op(36, OP_EQ, cell1->payload_len); tt_int_op(36, OP_EQ, cell2->payload_len); -#endif /* defined(HAVE_WORKING_TOR_TLS_GET_TLSSECRETS) */ tt_int_op(0, OP_EQ, cell1->circ_id); tt_int_op(0, OP_EQ, cell2->circ_id); tt_int_op(CELL_AUTH_CHALLENGE, OP_EQ, cell1->command); tt_int_op(CELL_AUTH_CHALLENGE, OP_EQ, cell2->command); -#ifdef HAVE_WORKING_TOR_TLS_GET_TLSSECRETS - tt_mem_op("\x00\x02\x00\x01\x00\x03", OP_EQ, cell1->payload + 32, 6); - tt_mem_op("\x00\x02\x00\x01\x00\x03", OP_EQ, cell2->payload + 32, 6); -#else tt_mem_op("\x00\x01\x00\x03", OP_EQ, cell1->payload + 32, 4); tt_mem_op("\x00\x01\x00\x03", OP_EQ, cell2->payload + 32, 4); -#endif /* defined(HAVE_WORKING_TOR_TLS_GET_TLSSECRETS) */ tt_mem_op(cell1->payload, OP_NE, cell2->payload, 32); done: @@ -1004,7 +994,6 @@ { (void)test; - testing__connection_or_pretend_TLSSECRET_is_supported = 1; authchallenge_data_t *d = tor_malloc_zero(sizeof(*d)); d->c = or_connection_new(CONN_TYPE_OR, AF_INET); d->chan = tor_malloc_zero(sizeof(*d->chan)); @@ -1019,7 +1008,7 @@ d->cell->payload_len = 38; d->cell->payload[33] = 2; /* 2 methods */ d->cell->payload[35] = 7; /* This one isn't real */ - d->cell->payload[37] = 1; /* This is the old RSA one. */ + d->cell->payload[37] = 3; /* This is the currently supported Ed25519 one. */ d->cell->command = CELL_AUTH_CHALLENGE; get_options_mutable()->ORPort_set = 1; @@ -1043,18 +1032,19 @@ }; static void -test_link_handshake_recv_authchallenge_ok(void *arg) +test_link_handshake_recv_authchallenge_no_ed25519(void *arg) { authchallenge_data_t *d = arg; + d->cell->payload[33] = 1; /* only 1 type supported. */ + d->cell->payload_len -= 2; + + setup_capture_of_logs(LOG_INFO); channel_tls_process_auth_challenge_cell(d->cell, d->chan); - tt_int_op(0, OP_EQ, mock_close_called); - tt_int_op(1, OP_EQ, d->c->handshake_state->received_auth_challenge); - tt_int_op(1, OP_EQ, mock_send_authenticate_called); - tt_int_op(1, OP_EQ, mock_send_netinfo_called); - tt_int_op(1, OP_EQ, mock_send_authenticate_called_with_type); /* RSA */ + expect_log_msg_containing("we don't know any of its authentication types"); + done: - ; + teardown_capture_of_logs(); } static void @@ -1154,14 +1144,6 @@ require_failure_message = "It had a nonzero circuit ID"; d->cell->circ_id = 1337) -static int -mock_get_tlssecrets(tor_tls_t *tls, uint8_t *secrets_out) -{ - (void)tls; - memcpy(secrets_out, "int getRandomNumber(){return 4;}", 32); - return 0; -} - static void mock_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd, @@ -1173,7 +1155,6 @@ } typedef struct authenticate_data_t { - int is_ed; or_connection_t *c1, *c2; channel_tls_t *chan2; var_cell_t *cell; @@ -1187,7 +1168,6 @@ UNMOCK(connection_or_write_var_cell_to_buf); UNMOCK(tor_tls_get_peer_cert); UNMOCK(tor_tls_get_own_cert); - UNMOCK(tor_tls_get_tlssecrets); UNMOCK(connection_or_close_for_error); UNMOCK(channel_set_circid_type); UNMOCK(tor_tls_export_key_material); @@ -1216,16 +1196,12 @@ authenticate_data_setup(const struct testcase_t *test) { authenticate_data_t *d = tor_malloc_zero(sizeof(*d)); - int is_ed = d->is_ed = (test->setup_data == (void*)3); - - testing__connection_or_pretend_TLSSECRET_is_supported = 1; scheduler_init(); MOCK(connection_or_write_var_cell_to_buf, mock_write_var_cell); MOCK(tor_tls_get_peer_cert, mock_get_peer_cert); MOCK(tor_tls_get_own_cert, mock_get_own_cert); - MOCK(tor_tls_get_tlssecrets, mock_get_tlssecrets); MOCK(connection_or_close_for_error, mock_close_for_err); MOCK(channel_set_circid_type, mock_set_circid_type); MOCK(tor_tls_export_key_material, mock_export_key_material); @@ -1265,7 +1241,7 @@ d->c2->tls = tor_tls_new(-1, 1); d->c2->handshake_state->received_certs_cell = 1; - const tor_x509_cert_t *id_cert=NULL, *link_cert=NULL, *auth_cert=NULL; + const tor_x509_cert_t *id_cert=NULL, *link_cert=NULL; tt_assert(! tor_tls_get_my_certs(1, &link_cert, &id_cert)); const uint8_t *der; @@ -1274,17 +1250,13 @@ d->c1->handshake_state->certs->id_cert = tor_x509_cert_decode(der, sz); d->c2->handshake_state->certs->id_cert = tor_x509_cert_decode(der, sz); - if (is_ed) { + { d->c1->handshake_state->certs->ed_id_sign = tor_cert_dup(get_master_signing_key_cert()); d->c2->handshake_state->certs->ed_id_sign = tor_cert_dup(get_master_signing_key_cert()); d->c2->handshake_state->certs->ed_sign_auth = tor_cert_dup(get_current_auth_key_cert()); - } else { - tt_assert(! tor_tls_get_my_certs(0, &auth_cert, &id_cert)); - tor_x509_cert_get_der(auth_cert, &der, &sz); - d->c2->handshake_state->certs->auth_cert = tor_x509_cert_decode(der, sz); } tor_x509_cert_get_der(link_cert, &der, &sz); @@ -1295,11 +1267,8 @@ tt_assert(mock_own_cert); /* Make an authenticate cell ... */ - int authtype; - if (is_ed) - authtype = AUTHTYPE_ED25519_SHA256_RFC5705; - else - authtype = AUTHTYPE_RSA_SHA256_TLSSECRET; + int authtype = AUTHTYPE_ED25519_SHA256_RFC5705; + tt_int_op(0, OP_EQ, connection_or_send_authenticate_cell(d->c1, authtype)); tt_assert(mock_got_var_cell); @@ -1327,50 +1296,27 @@ /* Is the cell well-formed on the outer layer? */ tt_int_op(d->cell->command, OP_EQ, CELL_AUTHENTICATE); tt_int_op(d->cell->payload[0], OP_EQ, 0); - if (d->is_ed) - tt_int_op(d->cell->payload[1], OP_EQ, 3); - else - tt_int_op(d->cell->payload[1], OP_EQ, 1); + tt_int_op(d->cell->payload[1], OP_EQ, 3); tt_int_op(ntohs(get_uint16(d->cell->payload + 2)), OP_EQ, d->cell->payload_len - 4); /* Check it out for plausibility... */ - auth_ctx_t ctx; - ctx.is_ed = d->is_ed; tt_int_op(d->cell->payload_len-4, OP_EQ, auth1_parse(&auth1, d->cell->payload+4, - d->cell->payload_len - 4, &ctx)); + d->cell->payload_len - 4)); tt_assert(auth1); - if (d->is_ed) { - tt_mem_op(auth1->type, OP_EQ, "AUTH0003", 8); - } else { - tt_mem_op(auth1->type, OP_EQ, "AUTH0001", 8); - } + tt_mem_op(auth1->type, OP_EQ, "AUTH0003", 8); tt_mem_op(auth1->tlssecrets, OP_EQ, "int getRandomNumber(){return 4;}", 32); /* Is the signature okay? */ const uint8_t *start = d->cell->payload+4, *end = auth1->end_of_signed; - if (d->is_ed) { + { ed25519_signature_t sig; tt_int_op(auth1_getlen_sig(auth1), OP_EQ, ED25519_SIG_LEN); memcpy(&sig.sig, auth1_getarray_sig(auth1), ED25519_SIG_LEN); tt_assert(!ed25519_checksig(&sig, start, end-start, &get_current_auth_keypair()->pubkey)); - } else { - uint8_t sig[128]; - uint8_t digest[32]; - tt_int_op(auth1_getlen_sig(auth1), OP_GT, 120); - auth_pubkey = tor_tls_cert_get_key( - d->c2->handshake_state->certs->auth_cert); - int n = crypto_pk_public_checksig( - auth_pubkey, - (char*)sig, sizeof(sig), (char*)auth1_getarray_sig(auth1), - auth1_getlen_sig(auth1)); - tt_int_op(n, OP_EQ, 32); - crypto_digest256((char*)digest, - (const char*)start, end-start, DIGEST_SHA256); - tt_mem_op(sig, OP_EQ, digest, 32); } /* Then feed it to c2. */ @@ -1378,12 +1324,9 @@ channel_tls_process_authenticate_cell(d->cell, d->chan2); tt_int_op(mock_close_called, OP_EQ, 0); tt_int_op(d->c2->handshake_state->authenticated, OP_EQ, 1); - if (d->is_ed) { + { tt_int_op(d->c2->handshake_state->authenticated_ed25519, OP_EQ, 1); tt_int_op(d->c2->handshake_state->authenticated_rsa, OP_EQ, 1); - } else { - tt_int_op(d->c2->handshake_state->authenticated_ed25519, OP_EQ, 0); - tt_int_op(d->c2->handshake_state->authenticated_rsa, OP_EQ, 1); } done: @@ -1445,11 +1388,6 @@ "certificate"; tor_x509_cert_free(d->c2->handshake_state->certs->id_cert); d->c2->handshake_state->certs->id_cert = NULL) -AUTHENTICATE_FAIL(noauthcert, - require_failure_message = "We never got an RSA " - "authentication certificate"; - tor_x509_cert_free(d->c2->handshake_state->certs->auth_cert); - d->c2->handshake_state->certs->auth_cert = NULL) AUTHENTICATE_FAIL(tooshort, require_failure_message = "Cell was way too short"; d->cell->payload_len = 3) @@ -1473,10 +1411,7 @@ "cell body was not as expected"; d->cell->payload[10] ^= 0xff) AUTHENTICATE_FAIL(badsig_1, - if (d->is_ed) - require_failure_message = "Ed25519 signature wasn't valid"; - else - require_failure_message = "RSA signature wasn't valid"; + require_failure_message = "Ed25519 signature wasn't valid"; d->cell->payload[d->cell->payload_len - 5] ^= 0xff) AUTHENTICATE_FAIL(missing_ed_id, { @@ -1522,10 +1457,13 @@ test_link_handshake_recv_certs_ ## name, TT_FORK, \ &setup_recv_certs, (void*)type } +/* These two used to have different behavior, but since we've + disabled RSA-SHAS256-TLSSecret authentication, we no longer + have any need to distinguish. +*/ #define TEST_AUTHENTICATE(name) \ { "authenticate/" #name , test_link_handshake_auth_ ## name, TT_FORK, \ &setup_authenticate, NULL } - #define TEST_AUTHENTICATE_ED(name) \ { "authenticate/" #name "_ed25519" , test_link_handshake_auth_ ## name, \ TT_FORK, &setup_authenticate, (void*)3 } @@ -1581,7 +1519,7 @@ TEST_RCV_CERTS(server_wrong_labels_1), TEST_RSA(send_authchallenge, TT_FORK), - TEST_RCV_AUTHCHALLENGE(ok), + TEST_RCV_AUTHCHALLENGE(no_ed25519), TEST_RCV_AUTHCHALLENGE(ok_ed25519), TEST_RCV_AUTHCHALLENGE(ok_noserver), TEST_RCV_AUTHCHALLENGE(ok_unrecognized), @@ -1603,7 +1541,6 @@ TEST_AUTHENTICATE(already_authenticated), TEST_AUTHENTICATE(nocerts), TEST_AUTHENTICATE(noidcert), - TEST_AUTHENTICATE(noauthcert), TEST_AUTHENTICATE(tooshort), TEST_AUTHENTICATE(badtype), TEST_AUTHENTICATE(truncated_1), diff -Nru tor-0.4.8.16/src/test/test_microdesc.c tor-0.4.9.6/src/test/test_microdesc.c --- tor-0.4.8.16/src/test/test_microdesc.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_microdesc.c 2026-03-25 14:30:34.000000000 +0000 @@ -366,38 +366,30 @@ "iFJkKxxDx7ksxX0zdl7aPT4ORFEuRhCYS6el7YJmoyg=\n" "-----END SIGNATURE-----\n"; -static const char test_md2_25[] = +static const char test_md2_withfamily_33[] = "onion-key\n" "-----BEGIN RSA PUBLIC KEY-----\n" "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n" "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n" "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n" "-----END RSA PUBLIC KEY-----\n" - "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n" - "p accept 1-65535\n" - "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n"; - -static const char test_md2_withfamily_28[] = - "onion-key\n" - "-----BEGIN RSA PUBLIC KEY-----\n" - "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n" - "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n" - "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n" - "-----END RSA PUBLIC KEY-----\n" - "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n" - "family OtherNode !Strange\n" + "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA\n" + "family !Strange $D219590AC9513BCDEBBA9AB721007A4CC01BBAE3 othernode\n" "p accept 1-65535\n" "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n"; -static const char test_md2_withfamily_29[] = +static const char test_md2_withfamilyids_35[] = "onion-key\n" "-----BEGIN RSA PUBLIC KEY-----\n" "MIGJAoGBAMvEJ/JVNK7I38PPWhQMuCgkET/ki4WIas4tj5Kmqfb9kHqxMR+EunRD\n" "83k4pel1yB7QdV+iTd/4SZOI8RpZP+BO1KnOTWfpztAU1lDGr19/PwdwcHaILpBD\n" "nNzm6otk4/bKUQ0vqpOfJljtg0DfAm4uMAQ6BMFy6uEAF7+JupuPAgMBAAE=\n" "-----END RSA PUBLIC KEY-----\n" - "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA=\n" + "ntor-onion-key FChIfm77vrWB7JsxQ+jMbN6VSSp1P0DYbw/2aqey4iA\n" "family !Strange $D219590AC9513BCDEBBA9AB721007A4CC01BBAE3 othernode\n" + "family-ids " + "ed25519:YWxsIGhhcHB5IGZhbWlsaWVzIGFyZSBhbGlrZSAtTFQ " + "rlwe:0YHRh9Cw0YHRgtC70LjQstGL0LUg0YHQtdC80YzQuC0\n" "p accept 1-65535\n" "id ed25519 J5lkRqyL6qW+CpN3E4RIlgJZeLgwjtmOOrjZvVhuwLQ\n"; @@ -411,21 +403,22 @@ ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL, NULL); tt_assert(ri); - md = dirvote_create_microdescriptor(ri, 25); - tt_str_op(md->body, OP_EQ, test_md2_25); - tt_assert(ed25519_pubkey_eq(md->ed25519_identity_pkey, - &ri->cache_info.signing_key_cert->signing_key)); - // Try family encoding. microdesc_free(md); ri->declared_family = smartlist_new(); smartlist_add_strdup(ri->declared_family, "OtherNode !Strange"); - md = dirvote_create_microdescriptor(ri, 28); - tt_str_op(md->body, OP_EQ, test_md2_withfamily_28); + md = dirvote_create_microdescriptor(ri, 33); + tt_str_op(md->body, OP_EQ, test_md2_withfamily_33); + // Try family-ids. microdesc_free(md); - md = dirvote_create_microdescriptor(ri, 29); - tt_str_op(md->body, OP_EQ, test_md2_withfamily_29); + ri->family_ids = smartlist_new(); + smartlist_add_strdup(ri->family_ids, + "ed25519:YWxsIGhhcHB5IGZhbWlsaWVzIGFyZSBhbGlrZSAtTFQ"); + smartlist_add_strdup(ri->family_ids, + "rlwe:0YHRh9Cw0YHRgtC70LjQstGL0LUg0YHQtdC80YzQuC0"); + md = dirvote_create_microdescriptor(ri, 35); + tt_str_op(md->body, OP_EQ, test_md2_withfamilyids_35); done: microdesc_free(md); @@ -792,6 +785,73 @@ teardown_capture_of_logs(); } +static void +test_md_parse_no_onion_key(void *arg) +{ + (void)arg; + + /* A correct MD with no onion key. */ + const char GOOD_MD[] = + "onion-key\n" + "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n" + "id ed25519 VGhpcyBpc24ndCBhY3R1YWxseSBhIHB1YmxpYyBrZXk\n"; + + smartlist_t *mds = NULL; + + mds = microdescs_parse_from_string(GOOD_MD, + NULL, 1, SAVED_NOWHERE, NULL); + tt_assert(mds); + tt_int_op(smartlist_len(mds), OP_EQ, 1); + const microdesc_t *md = smartlist_get(mds, 0); + tt_mem_op(md->ed25519_identity_pkey, OP_EQ, + "This isn't actually a public key", ED25519_PUBKEY_LEN); + + done: + if (mds) { + SMARTLIST_FOREACH(mds, microdesc_t *, m, microdesc_free(m)); + smartlist_free(mds); + } + teardown_capture_of_logs(); +} + +static void +test_md_parse_family_ids(void *arg) +{ + (void)arg; + + const char GOOD_MDS[] = + "onion-key\n" + "ntor-onion-key VHlycmFueSwgbGlrZSBoZWxsLCBpcyBub3QgZWFzaWw\n" + "id ed25519 eSBjb25xdWVyZWQ7IHlldCB3ZSBoYXZlIHRoaXMgY28\n" + "family-ids\n" + "onion-key\n" + "ntor-onion-key bnNvbGF0aW9uIHdpdGggdXMsIHRoYXQgdGhlIGhhcmQ\n" + "id ed25519 ZXIgdGhlIGNvbmZsaWN0LCB0aGUgbW9yZSBnbG9yaW8\n" + "family-ids ed25519:dXMgdGhlIHRyaXVtcGguICAgIC1UaG9tYXMgUGFpbmU " + "other:Example\n"; + smartlist_t *mds = NULL; + mds = microdescs_parse_from_string(GOOD_MDS, NULL, 1, SAVED_NOWHERE, NULL); + tt_assert(mds); + tt_int_op(smartlist_len(mds), OP_EQ, 2); + + const microdesc_t *md1 = smartlist_get(mds, 0); + tt_ptr_op(md1->family_ids, OP_EQ, NULL); + + const microdesc_t *md2 = smartlist_get(mds, 1); + tt_ptr_op(md2->family_ids, OP_NE, NULL); + tt_int_op(smartlist_len(md2->family_ids), OP_EQ, 2); + tt_str_op(smartlist_get(md2->family_ids, 0), OP_EQ, + "ed25519:dXMgdGhlIHRyaXVtcGguICAgIC1UaG9tYXMgUGFpbmU"); + tt_str_op(smartlist_get(md2->family_ids, 1), OP_EQ, + "other:Example"); + + done: + if (mds) { + SMARTLIST_FOREACH(mds, microdesc_t *, m, microdesc_free(m)); + smartlist_free(mds); + } +} + static int mock_rgsbd_called = 0; static routerstatus_t *mock_rgsbd_val_a = NULL; static routerstatus_t *mock_rgsbd_val_b = NULL; @@ -926,6 +986,8 @@ { "generate", test_md_generate, 0, NULL, NULL }, { "parse", test_md_parse, 0, NULL, NULL }, { "parse_id_ed25519", test_md_parse_id_ed25519, 0, NULL, NULL }, + { "parse_no_onion_key", test_md_parse_no_onion_key, 0, NULL, NULL }, + { "parse_family_ids", test_md_parse_family_ids, 0, NULL, NULL }, { "reject_cache", test_md_reject_cache, TT_FORK, NULL, NULL }, { "corrupt_desc", test_md_corrupt_desc, TT_FORK, NULL, NULL }, END_OF_TESTCASES diff -Nru tor-0.4.8.16/src/test/test_nodelist.c tor-0.4.9.6/src/test/test_nodelist.c --- tor-0.4.8.16/src/test/test_nodelist.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_nodelist.c 2026-03-25 14:30:34.000000000 +0000 @@ -559,34 +559,34 @@ memcpy(mock_node2.identity, "SecondNodeWe'reTestn", DIGEST_LEN); // empty families. - tt_assert(! node_family_contains(&mock_node1, &mock_node2)); - tt_assert(! node_family_contains(&mock_node2, &mock_node1)); + tt_assert(! node_family_list_contains(&mock_node1, &mock_node2)); + tt_assert(! node_family_list_contains(&mock_node2, &mock_node1)); // Families contain nodes, but not these nodes mock_ri.declared_family = smartlist_new(); smartlist_add(mock_ri.declared_family, (char*)"NodeThree"); mock_md.family = nodefamily_parse("NodeFour", NULL, 0); - tt_assert(! node_family_contains(&mock_node1, &mock_node2)); - tt_assert(! node_family_contains(&mock_node2, &mock_node1)); + tt_assert(! node_family_list_contains(&mock_node1, &mock_node2)); + tt_assert(! node_family_list_contains(&mock_node2, &mock_node1)); // Families contain one another. smartlist_add(mock_ri.declared_family, (char*) "4e6f64654f6e654e6f6465314e6f64654f6e6531"); - tt_assert(! node_family_contains(&mock_node1, &mock_node2)); - tt_assert(node_family_contains(&mock_node2, &mock_node1)); + tt_assert(! node_family_list_contains(&mock_node1, &mock_node2)); + tt_assert(node_family_list_contains(&mock_node2, &mock_node1)); nodefamily_free(mock_md.family); mock_md.family = nodefamily_parse( "NodeFour " "5365636f6e644e6f64655765277265546573746e", NULL, 0); - tt_assert(node_family_contains(&mock_node1, &mock_node2)); - tt_assert(node_family_contains(&mock_node2, &mock_node1)); + tt_assert(node_family_list_contains(&mock_node1, &mock_node2)); + tt_assert(node_family_list_contains(&mock_node2, &mock_node1)); // Try looking up families now. MOCK(node_get_by_nickname, mock_node_get_by_nickname); MOCK(node_get_by_id, mock_node_get_by_id); - node_lookup_declared_family(nodes, &mock_node1); + node_lookup_declared_family_list(nodes, &mock_node1); tt_int_op(smartlist_len(nodes), OP_EQ, 2); const node_t *n = smartlist_get(nodes, 0); tt_mem_op(n->identity, OP_EQ, "SecondNodeWe'reTestn", DIGEST_LEN); @@ -597,7 +597,7 @@ SMARTLIST_FOREACH(nodes, node_t *, x, tor_free(x)); smartlist_clear(nodes); - node_lookup_declared_family(nodes, &mock_node2); + node_lookup_declared_family_list(nodes, &mock_node2); tt_int_op(smartlist_len(nodes), OP_EQ, 2); n = smartlist_get(nodes, 0); // This gets a truncated hex hex ID since it was looked up by name diff -Nru tor-0.4.8.16/src/test/test_ntor_v3.c tor-0.4.9.6/src/test/test_ntor_v3.c --- tor-0.4.8.16/src/test/test_ntor_v3.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_ntor_v3.c 2026-03-25 14:30:34.000000000 +0000 @@ -192,6 +192,7 @@ uint8_t client_keys[CELL_PAYLOAD_SIZE]; uint8_t rend_auth[DIGEST_LEN]; + info.supports_ntor_v3 = true; info.exit_supports_congestion_control = 1; unhex(relay_onion_key.seckey.secret_key, @@ -218,18 +219,20 @@ server_keys.junk_keypair = &handshake_state.u.ntor3->client_keypair; + size_t serv_keylen = sizeof(serv_keys); + size_t client_keylen = sizeof(serv_keys); reply_len = onion_skin_server_handshake(ONION_HANDSHAKE_TYPE_NTOR_V3, onionskin, onionskin_len, &server_keys, serv_params_in, serv_reply, sizeof(serv_reply), - serv_keys, sizeof(serv_keys), + serv_keys, &serv_keylen, rend_nonce, serv_params_out); tt_int_op(reply_len, OP_NE, -1); tt_int_op(onion_skin_client_handshake(ONION_HANDSHAKE_TYPE_NTOR_V3, &handshake_state, serv_reply, reply_len, - client_keys, sizeof(client_keys), + client_keys, &client_keylen, rend_auth, client_params_out, NULL), OP_EQ, 0); diff -Nru tor-0.4.8.16/src/test/test_proto_http.c tor-0.4.9.6/src/test/test_proto_http.c --- tor-0.4.8.16/src/test/test_proto_http.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_proto_http.c 2026-03-25 14:30:34.000000000 +0000 @@ -6,11 +6,14 @@ * \brief Tests for our HTTP protocol parser code */ +#define CONNECTION_EDGE_PRIVATE + #include "core/or/or.h" #include "test/test.h" #include "lib/buf/buffers.h" #include "core/proto/proto_http.h" #include "test/log_test_helpers.h" +#include "core/or/connection_edge.h" #define S(str) str, sizeof(str)-1 @@ -203,11 +206,33 @@ teardown_capture_of_logs(); } +static void +test_proto_http_proxy_auth(void *arg) +{ + (void)arg; + + tt_assert(using_old_proxy_auth("")); + tt_assert(using_old_proxy_auth("Foo Bar")); + tt_assert(using_old_proxy_auth("Basicish Bar")); + tt_assert(using_old_proxy_auth("Basic")); + tt_assert(using_old_proxy_auth("Basic x")); + // encodes foo:bar + tt_assert(using_old_proxy_auth("Basic Zm9vOmJhcg==")); + // encodes torx:bar + tt_assert(using_old_proxy_auth("Basic dG9yeDpiYXI=")); + + // encodes tor:random + tt_assert(! using_old_proxy_auth("Basic dG9yOnJhbmRvbQ==")); + + done: + ; +} + struct testcase_t proto_http_tests[] = { { "peek", test_proto_http_peek, 0, NULL, NULL }, { "valid", test_proto_http_valid, 0, NULL, NULL }, { "invalid", test_proto_http_invalid, 0, NULL, NULL }, + { "proxyauth", test_proto_http_proxy_auth, 0, NULL, NULL }, END_OF_TESTCASES }; - diff -Nru tor-0.4.8.16/src/test/test_protover.c tor-0.4.9.6/src/test/test_protover.c --- tor-0.4.8.16/src/test/test_protover.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_protover.c 2026-03-25 14:30:34.000000000 +0000 @@ -219,15 +219,15 @@ tt_str_op(msg, OP_EQ, "Link=6-60"); tor_free(msg); tt_assert(! protover_all_supported("Link=1-3,50-63", &msg)); - tt_str_op(msg, OP_EQ, "Link=50-63"); + tt_str_op(msg, OP_EQ, "Link=1-2,50-63"); tor_free(msg); tt_assert(! protover_all_supported("Link=1-3,5-12", &msg)); - tt_str_op(msg, OP_EQ, "Link=6-12"); + tt_str_op(msg, OP_EQ, "Link=1-2,6-12"); tor_free(msg); /* Mix of protocols we do support and some we don't, where the protocols * we do support have some versions we don't support. */ - tt_assert(! protover_all_supported("Link=1-3,5-12 Quokka=40-41", &msg)); + tt_assert(! protover_all_supported("Link=3,5-12 Quokka=40-41", &msg)); tt_str_op(msg, OP_EQ, "Link=6-12 Quokka=40-41"); tor_free(msg); @@ -329,7 +329,7 @@ * headers. */ #define PROTOVER_LINKAUTH_V1 1 #define PROTOVER_LINKAUTH_V2 2 -#define PROTOVER_RELAY_V1 1 +#define PROTOVER_RELAY_V2 2 /* Deprecated HSIntro versions */ #define PROTOVER_HS_INTRO_DEPRECATED_1 1 @@ -397,7 +397,7 @@ /* Relay protovers do not appear anywhere in the code. */ tt_assert(protocol_list_supports_protocol(supported_protocols, PRT_RELAY, - PROTOVER_RELAY_V1)); + PROTOVER_RELAY_V2)); tt_assert(protocol_list_supports_protocol(supported_protocols, PRT_RELAY, PROTOVER_RELAY_EXTEND2)); diff -Nru tor-0.4.8.16/src/test/test_rebind.sh tor-0.4.9.6/src/test/test_rebind.sh --- tor-0.4.8.16/src/test/test_rebind.sh 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_rebind.sh 2026-03-25 14:30:34.000000000 +0000 @@ -48,7 +48,7 @@ tmpdir= # For some reasons, shellcheck is not seeing that we can call this # function from the trap below. -# shellcheck disable=SC2317 +# shellcheck disable=SC2317,SC2329 clean () { if [ -n "$tmpdir" ] && [ -d "$tmpdir" ]; then ls -l "$tmpdir" diff -Nru tor-0.4.8.16/src/test/test_relaycell.c tor-0.4.9.6/src/test/test_relaycell.c --- tor-0.4.8.16/src/test/test_relaycell.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_relaycell.c 2026-03-25 14:30:34.000000000 +0000 @@ -19,6 +19,7 @@ #include "core/or/connection_edge.h" #include "core/or/sendme.h" #include "core/or/relay.h" +#include "core/or/relay_msg.h" #include "test/test.h" #include "test/log_test_helpers.h" @@ -172,19 +173,20 @@ return entryconn; } -#define PACK_CELL(id, cmd, body_s) do { \ - memset(&cell, 0, sizeof(cell)); \ - memset(&rh, 0, sizeof(rh)); \ - memcpy(cell.payload+RELAY_HEADER_SIZE, (body_s), sizeof((body_s))-1); \ - rh.length = sizeof((body_s))-1; \ - rh.command = (cmd); \ - rh.stream_id = (id); \ - relay_header_pack((uint8_t*)&cell.payload, &rh); \ +#define PACK_CELL(id, cmd, body_s) do { \ + len_tmp = sizeof(body_s)-1; \ + relay_msg_free(msg); \ + msg = tor_malloc_zero(sizeof(relay_msg_t)); \ + msg->command = (cmd); \ + msg->stream_id = (id); \ + msg->body = cell_buf; \ + msg->length = len_tmp; \ + memcpy(cell_buf, (body_s), len_tmp); \ } while (0) #define ASSERT_COUNTED_BW() do { \ - tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered+rh.length); \ + tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered+msg->length); \ tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ, \ - overhead+RELAY_PAYLOAD_SIZE-rh.length); \ + overhead+RELAY_PAYLOAD_SIZE-msg->length); \ delivered = circ->n_delivered_read_circ_bw; \ overhead = circ->n_overhead_read_circ_bw; \ } while (0) @@ -196,14 +198,15 @@ static int subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) { - cell_t cell; - relay_header_t rh; + relay_msg_t *msg = NULL; + size_t len_tmp; edge_connection_t *edgeconn; entry_connection_t *entryconn2=NULL; entry_connection_t *entryconn3=NULL; entry_connection_t *entryconn4=NULL; int delivered = circ->n_delivered_read_circ_bw; int overhead = circ->n_overhead_read_circ_bw; + uint8_t cell_buf[RELAY_PAYLOAD_SIZE_MAX]; /* Make new entryconns */ entryconn2 = fake_entry_conn(circ, init_id); @@ -225,36 +228,36 @@ /* Data cell not in the half-opened list */ PACK_CELL(4000, RELAY_COMMAND_DATA, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Sendme cell not in the half-opened list */ PACK_CELL(4000, RELAY_COMMAND_SENDME, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Connected cell not in the half-opened list */ PACK_CELL(4000, RELAY_COMMAND_CONNECTED, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Resolved cell not in the half-opened list */ PACK_CELL(4000, RELAY_COMMAND_RESOLVED, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -262,9 +265,9 @@ edgeconn = ENTRY_TO_EDGE_CONN(entryconn2); PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -273,9 +276,9 @@ ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); data_cells--; @@ -283,9 +286,9 @@ ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -294,9 +297,9 @@ ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); sendme_cells--; @@ -304,9 +307,9 @@ ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -314,18 +317,18 @@ ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -335,7 +338,7 @@ /* sendme cell on open entryconn with full window */ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); int ret = - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); tt_int_op(ret, OP_EQ, -END_CIRC_REASON_TORPROTOCOL); ASSERT_UNCOUNTED_BW(); @@ -346,18 +349,18 @@ connection_edge_reached_eof(edgeconn); PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -365,16 +368,16 @@ ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); ret = - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); tt_int_op(ret, OP_NE, -END_CIRC_REASON_TORPROTOCOL); ASSERT_UNCOUNTED_BW(); @@ -382,9 +385,9 @@ ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -400,16 +403,16 @@ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED, "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED, "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -417,9 +420,9 @@ ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -427,17 +430,19 @@ ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); + relay_msg_free(msg); connection_free_minimal(ENTRY_TO_CONN(entryconn2)); connection_free_minimal(ENTRY_TO_CONN(entryconn3)); connection_free_minimal(ENTRY_TO_CONN(entryconn4)); return 1; done: + relay_msg_free(msg); connection_free_minimal(ENTRY_TO_CONN(entryconn2)); connection_free_minimal(ENTRY_TO_CONN(entryconn3)); connection_free_minimal(ENTRY_TO_CONN(entryconn4)); @@ -666,14 +671,15 @@ static void test_circbw_relay(void *arg) { - cell_t cell; - relay_header_t rh; + relay_msg_t *msg = NULL; + size_t len_tmp; tor_addr_t addr; edge_connection_t *edgeconn; entry_connection_t *entryconn1=NULL; origin_circuit_t *circ; int delivered = 0; int overhead = 0; + uint8_t cell_buf[RELAY_PAYLOAD_SIZE_MAX]; (void)arg; @@ -692,23 +698,22 @@ /* Stream id 0: Not counted */ PACK_CELL(0, RELAY_COMMAND_END, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Stream id 1: Counted */ PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); /* Properly formatted connect cell: counted */ PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234"); tor_addr_parse(&addr, "30.40.50.60"); - rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE, - &addr, 1024); - relay_header_pack((uint8_t*)&cell.payload, &rh); \ - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + msg->length = connected_cell_format_payload(cell_buf, + &addr, 1024); + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); @@ -718,7 +723,7 @@ edgeconn->on_circuit = TO_CIRCUIT(circ); PACK_CELL(1, RELAY_COMMAND_RESOLVED, "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); @@ -727,65 +732,65 @@ /* Connected cell after open: not counted */ PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Resolved cell after open: not counted */ PACK_CELL(1, RELAY_COMMAND_RESOLVED, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Drop cell: not counted */ PACK_CELL(1, RELAY_COMMAND_DROP, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Data cell on stream 0: not counted */ PACK_CELL(0, RELAY_COMMAND_DATA, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Data cell on open connection: counted */ ENTRY_TO_CONN(entryconn1)->marked_for_close = 0; PACK_CELL(1, RELAY_COMMAND_DATA, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); /* Empty Data cell on open connection: not counted */ ENTRY_TO_CONN(entryconn1)->marked_for_close = 0; PACK_CELL(1, RELAY_COMMAND_DATA, ""); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Sendme on valid stream: counted */ edgeconn->package_window -= STREAMWINDOW_INCREMENT; PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); /* Sendme on valid stream with full window: not counted */ PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234"); edgeconn->package_window = STREAMWINDOW_START; - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Sendme on unknown stream: not counted */ PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Sendme on circuit with full window: not counted */ PACK_CELL(0, RELAY_COMMAND_SENDME, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -796,44 +801,44 @@ circ->cpath->package_window = 901; sendme_record_cell_digest_on_circ(TO_CIRCUIT(circ), circ->cpath); circ->cpath->package_window = 900; - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); /* Invalid extended cell: not counted */ PACK_CELL(1, RELAY_COMMAND_EXTENDED2, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Invalid extended cell: not counted */ PACK_CELL(1, RELAY_COMMAND_EXTENDED, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Invalid HS cell: not counted */ PACK_CELL(1, RELAY_COMMAND_ESTABLISH_INTRO, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* "Valid" HS cell in expected state: counted */ TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND; PACK_CELL(1, RELAY_COMMAND_RENDEZVOUS_ESTABLISHED, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); /* End cell on non-closed connection: counted */ PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); /* End cell on connection that already got one: not counted */ PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -848,10 +853,11 @@ /* Path bias: truncated */ tt_int_op(circ->base_.marked_for_close, OP_EQ, 0); PACK_CELL(0, RELAY_COMMAND_TRUNCATED, "Data1234"); - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); tt_int_op(circ->base_.marked_for_close, OP_EQ, 1); done: + relay_msg_free(msg); UNMOCK(connection_start_reading); UNMOCK(connection_mark_unattached_ap_); UNMOCK(connection_mark_for_close_internal_); @@ -872,17 +878,19 @@ { entry_connection_t *entryconn; edge_connection_t *edgeconn; - cell_t cell; - relay_header_t rh; + relay_msg_t *msg = NULL; int r; or_options_t *options = get_options_mutable(); + size_t len_tmp; + uint8_t cell_buf[RELAY_PAYLOAD_SIZE_MAX]; #define SET_CELL(s) do { \ - memset(&cell, 0, sizeof(cell)); \ - memset(&rh, 0, sizeof(rh)); \ - memcpy(cell.payload + RELAY_HEADER_SIZE, (s), sizeof((s))-1); \ - rh.length = sizeof((s))-1; \ - rh.command = RELAY_COMMAND_RESOLVED; \ + relay_msg_free(msg); \ + msg = tor_malloc_zero(sizeof(relay_msg_t)); \ + len_tmp = sizeof(s) - 1; \ + msg->body = cell_buf; \ + msg->length = len_tmp; \ + memcpy(cell_buf, s, len_tmp); \ } while (0) #define MOCK_RESET() do { \ srm_ncalls = mum_ncalls = 0; \ @@ -892,20 +900,20 @@ tt_ptr_op(mum_conn, OP_EQ, entryconn); \ tt_int_op(mum_endreason, OP_EQ, (reason)); \ } while (0) -#define ASSERT_RESOLVED_CALLED(atype, answer, ttl, expires) do { \ - tt_int_op(srm_ncalls, OP_EQ, 1); \ - tt_ptr_op(srm_conn, OP_EQ, entryconn); \ - tt_int_op(srm_atype, OP_EQ, (atype)); \ - if ((answer) != NULL) { \ - tt_int_op(srm_alen, OP_EQ, sizeof(answer)-1); \ - tt_int_op(srm_alen, OP_LT, 512); \ - tt_int_op(srm_answer_is_set, OP_EQ, 1); \ - tt_mem_op(srm_answer, OP_EQ, answer, sizeof(answer)-1); \ - } else { \ - tt_int_op(srm_answer_is_set, OP_EQ, 0); \ - } \ - tt_int_op(srm_ttl, OP_EQ, ttl); \ - tt_i64_op(srm_expires, OP_EQ, expires); \ +#define ASSERT_RESOLVED_CALLED(atype, answer, ttl, expires) do { \ + tt_int_op(srm_ncalls, OP_EQ, 1); \ + tt_ptr_op(srm_conn, OP_EQ, entryconn); \ + tt_int_op(srm_atype, OP_EQ, (atype)); \ + if ((answer) != NULL) { \ + tt_int_op(srm_alen, OP_EQ, sizeof(answer)-1); \ + tt_int_op(srm_alen, OP_LT, 512); \ + tt_int_op(srm_answer_is_set, OP_EQ, 1); \ + tt_mem_op(srm_answer, OP_EQ, answer, sizeof(answer)-1); \ + } else { \ + tt_int_op(srm_answer_is_set, OP_EQ, 0); \ + } \ + tt_int_op(srm_ttl, OP_EQ, ttl); \ + tt_i64_op(srm_expires, OP_EQ, expires); \ } while (0) (void)arg; @@ -930,7 +938,7 @@ /* Try with connection in non-RESOLVE_WAIT state: cell gets ignored */ MOCK_RESET(); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); tt_int_op(srm_ncalls, OP_EQ, 0); tt_int_op(mum_ncalls, OP_EQ, 0); @@ -944,7 +952,7 @@ /* We prefer ipv4, so we should get the first ipv4 answer */ MOCK_RESET(); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -953,7 +961,7 @@ /* But we may be discarding private answers. */ MOCK_RESET(); options->ClientDNSRejectInternalAddresses = 1; - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -962,7 +970,7 @@ /* now prefer ipv6, and get the first ipv6 answer */ entryconn->entry_cfg.prefer_ipv6 = 1; MOCK_RESET(); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -974,7 +982,7 @@ /* With a cell that only has IPv4, we report IPv4 even if we prefer IPv6 */ MOCK_RESET(); SET_CELL("\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -984,17 +992,17 @@ * ipv4 */ MOCK_RESET(); entryconn->entry_cfg.ipv4_traffic = 0; - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); - ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR, NULL, -1, -1); + ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_NOERROR, NULL, -1, -1); /* If we wanted hostnames, we report nothing, since we only had IPs. */ MOCK_RESET(); entryconn->entry_cfg.ipv4_traffic = 1; entryconn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -1003,7 +1011,7 @@ /* A hostname cell is fine though. */ MOCK_RESET(); SET_CELL("\x00\x0fwww.example.com\x00\x01\x00\x00"); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -1013,7 +1021,7 @@ MOCK_RESET(); entryconn->socks_request->command = SOCKS_COMMAND_RESOLVE; SET_CELL("\x04\x04\x01\x02\x03\x04"); /* no ttl */ - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_TORPROTOCOL); tt_int_op(srm_ncalls, OP_EQ, 0); @@ -1024,7 +1032,7 @@ "\x04\x04\x7f\x00\x01\x02\x00\x00\x01\x00" /* IPv4: 192.168.1.1, ttl 256 */ "\x04\x04\xc0\xa8\x01\x01\x00\x00\x01\x00"); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_TORPROTOCOL); ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR_TRANSIENT, NULL, 0, TIME_MAX); @@ -1032,13 +1040,14 @@ /* Legit error code */ MOCK_RESET(); SET_CELL("\xf0\x15" "quiet and meaningless" "\x00\x00\x0f\xff"); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR_TRANSIENT, NULL, -1, -1); done: + relay_msg_free(msg); UNMOCK(connection_mark_unattached_ap_); UNMOCK(connection_ap_handshake_socks_resolved); } diff -Nru tor-0.4.8.16/src/test/test_relaycrypt.c tor-0.4.9.6/src/test/test_relaycrypt.c --- tor-0.4.8.16/src/test/test_relaycrypt.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_relaycrypt.c 2026-03-25 14:30:34.000000000 +0000 @@ -19,11 +19,18 @@ #include "test/test.h" -static const char KEY_MATERIAL[3][CPATH_KEY_MATERIAL_LEN] = { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wattributes" +#endif +NONSTRING static const char KEY_MATERIAL[3][CPATH_KEY_MATERIAL_LEN] = { " 'My public key is in this signed x509 object', said Tom assertively.", "'Let's chart the pedal phlanges in the tomb', said Tom cryptographically", " 'Segmentation fault bugs don't _just happen_', said Tom seethingly.", }; +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif typedef struct testing_circuitset_t { or_circuit_t *or_circ[3]; @@ -42,17 +49,18 @@ for (i=0; i<3; ++i) { cs->or_circ[i] = or_circuit_new(0, NULL); tt_int_op(0, OP_EQ, - relay_crypto_init(&cs->or_circ[i]->crypto, - KEY_MATERIAL[i], sizeof(KEY_MATERIAL[i]), - 0, 0)); + relay_crypto_init(RELAY_CRYPTO_ALG_TOR1, + &cs->or_circ[i]->crypto, + KEY_MATERIAL[i], sizeof(KEY_MATERIAL[i]))); } cs->origin_circ = origin_circuit_new(); cs->origin_circ->base_.purpose = CIRCUIT_PURPOSE_C_GENERAL; for (i=0; i<3; ++i) { crypt_path_t *hop = tor_malloc_zero(sizeof(*hop)); - relay_crypto_init(&hop->pvt_crypto, KEY_MATERIAL[i], - sizeof(KEY_MATERIAL[i]), 0, 0); + relay_crypto_init(RELAY_CRYPTO_ALG_TOR1, + &hop->pvt_crypto, KEY_MATERIAL[i], + sizeof(KEY_MATERIAL[i])); hop->state = CPATH_STATE_OPEN; cpath_extend_linked_list(&cs->origin_circ->cpath, hop); tt_ptr_op(hop, OP_EQ, cs->origin_circ->cpath->prev); @@ -189,4 +197,3 @@ TEST(inbound), END_OF_TESTCASES }; - diff -Nru tor-0.4.8.16/src/test/test_router.c tor-0.4.9.6/src/test/test_router.c --- tor-0.4.8.16/src/test/test_router.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_router.c 2026-03-25 14:30:34.000000000 +0000 @@ -60,8 +60,8 @@ mock_routerinfo->identity_pkey = crypto_pk_dup_key(ident_key); mock_routerinfo->protocol_list = tor_strdup("Cons=1-2 Desc=1-2 DirCache=1-2"); - router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->onion_pkey, - &mock_routerinfo->onion_pkey_len); + router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->tap_onion_pkey, + &mock_routerinfo->tap_onion_pkey_len); mock_routerinfo->bandwidthrate = 9001; mock_routerinfo->bandwidthburst = 9002; diff -Nru tor-0.4.8.16/src/test/test_routerkeys.c tor-0.4.9.6/src/test/test_routerkeys.c --- tor-0.4.8.16/src/test/test_routerkeys.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_routerkeys.c 2026-03-25 14:30:34.000000000 +0000 @@ -5,6 +5,7 @@ #include "orconfig.h" #define ROUTER_PRIVATE +#define ROUTERKEYS_PRIVATE #include "core/or/or.h" #include "app/config/config.h" #include "feature/relay/router.h" @@ -735,6 +736,87 @@ tor_free(cc); } +static void +test_routerkeys_family_key_fname(void *arg) +{ + (void)arg; + + tt_assert(is_family_key_fname("hello.secret_family_key")); + tt_assert(is_family_key_fname("xyzzy.secret_family_key")); + tt_assert(is_family_key_fname("909.secret_family_key")); + tt_assert(! is_family_key_fname("zzz.secret_family_key~")); + tt_assert(! is_family_key_fname("secret_family_key")); + + done: + ; +} + +static void +test_routerkeys_load_family_keys(void *arg) +{ + (void) arg; + char *dname = tor_strdup(get_fname_rnd("fkeys")); + char *fname = NULL; + or_options_t *options = get_options_mutable(); + ed25519_public_key_t pubkey; + +#ifdef _WIN32 + tt_assert(0==mkdir(dname)); +#else + tt_assert(0==mkdir(dname,0700)); +#endif + + options->FamilyIds = smartlist_new(); + + // Not a family key, will be ignored + tor_asprintf(&fname, "%s"PATH_SEPARATOR"junk.1", dname); + write_str_to_file(fname, "hello world", 0); + tor_free(fname); + + tt_int_op(0, OP_EQ, load_family_id_keys_impl(options, dname)); + tt_int_op(0, OP_EQ, smartlist_len(get_current_family_id_keys())); + + // Create a family key; make sure we can load it. + tor_asprintf(&fname, "%s"PATH_SEPARATOR"cg.secret_family_key", dname); + tt_int_op(0, OP_EQ, create_family_id_key(fname, &pubkey)); + tor_free(fname); + smartlist_add(options->FamilyIds, tor_memdup(&pubkey, sizeof(pubkey))); + + tt_int_op(0, OP_EQ, load_family_id_keys_impl(options, dname)); + tt_int_op(1, OP_EQ, smartlist_len(get_current_family_id_keys())); + + //Try a second key. + tor_asprintf(&fname, "%s"PATH_SEPARATOR"eb.secret_family_key", dname); + tt_int_op(0, OP_EQ, create_family_id_key(fname, &pubkey)); + smartlist_add(options->FamilyIds, tor_memdup(&pubkey, sizeof(pubkey))); + tor_free(fname); + + tt_int_op(0, OP_EQ, load_family_id_keys_impl(options, dname)); + tt_int_op(2, OP_EQ, smartlist_len(get_current_family_id_keys())); + + // Try an unlisted key, make sure it isn't loaded. + tor_asprintf(&fname, "%s"PATH_SEPARATOR"gt.secret_family_key", dname); + tt_int_op(0, OP_EQ, create_family_id_key(fname, &pubkey)); + // Do not add to FamilyIDs here; we're leaving it unlisted. + tor_free(fname); + + tt_int_op(0, OP_EQ, load_family_id_keys_impl(options, dname)); + tt_int_op(2, OP_EQ, smartlist_len(get_current_family_id_keys())); + + // Make a junk key, make sure it causes an error. + tor_asprintf(&fname, "%s"PATH_SEPARATOR"xyz.secret_family_key", dname); + write_str_to_file(fname, "hello world", 0); + tor_free(fname); + + tt_int_op(-1, OP_EQ, load_family_id_keys_impl(options, dname)); + // keys unchanged + tt_int_op(2, OP_EQ, smartlist_len(get_current_family_id_keys())); + + done: + tor_free(dname); + tor_free(fname); +} + #define TEST(name, flags) \ { #name , test_routerkeys_ ## name, (flags), NULL, NULL } @@ -749,5 +831,7 @@ TEST(cross_certify_ntor, 0), TEST(cross_certify_tap, 0), TEST(rsa_ed_crosscert, 0), + TEST(family_key_fname, 0), + TEST(load_family_keys, TT_FORK), END_OF_TESTCASES }; diff -Nru tor-0.4.8.16/src/test/test_sandbox.c tor-0.4.9.6/src/test/test_sandbox.c --- tor-0.4.8.16/src/test/test_sandbox.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_sandbox.c 2026-03-25 14:30:34.000000000 +0000 @@ -364,22 +364,32 @@ struct testcase_t sandbox_tests[] = { SANDBOX_TEST(is_active, TT_FORK), -/* When Tor is built with fragile compiler-hardening the sandbox is unable to - * filter requests to open files or directories (on systems where glibc uses - * the "open" system call to provide this functionality), as doing so would +/* When Tor is built with fragile compiler-hardening the sandbox is usually + * unable to filter requests to open files or directories, as doing so would * interfere with the address sanitizer as it retrieves information about the * running process via the filesystem. Skip these tests in that case as the * corresponding functions are likely to have no effect and this will cause the * tests to fail. */ #ifdef ENABLE_FRAGILE_HARDENING SANDBOX_TEST_SKIPPED(open_filename), + SANDBOX_TEST_SKIPPED(openat_filename), SANDBOX_TEST_SKIPPED(opendir_dirname), #else SANDBOX_TEST_IN_SANDBOX(open_filename), - SANDBOX_TEST_IN_SANDBOX(opendir_dirname), + SANDBOX_TEST_IN_SANDBOX(openat_filename), #endif /* defined(ENABLE_FRAGILE_HARDENING) */ - SANDBOX_TEST_IN_SANDBOX(openat_filename), + /* Ok why... Quick answer is #40918. This has been failing on Debian SID + * making us unable to have nightly packages which is a problem as we have + * several relay operators using them and actively reporting us issues with + * them. This test fails due to the sandbox denying it. + * + * We are deprecating C-tor slowly and honestly, the Sandbox feature has + * always been a source of pain and unhappiness. Disable this as finding why, + * fixing it and hoping it doesn't come back will mostly be a waste of our + * time at this point. */ + SANDBOX_TEST_SKIPPED(opendir_dirname), + SANDBOX_TEST_IN_SANDBOX(chmod_filename), SANDBOX_TEST_IN_SANDBOX(chown_filename), SANDBOX_TEST_IN_SANDBOX(rename_filename), diff -Nru tor-0.4.8.16/src/test/test_sendme.c tor-0.4.9.6/src/test/test_sendme.c --- tor-0.4.8.16/src/test/test_sendme.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_sendme.c 2026-03-25 14:30:34.000000000 +0000 @@ -7,6 +7,7 @@ #define NETWORKSTATUS_PRIVATE #define SENDME_PRIVATE #define RELAY_PRIVATE +#define RELAY_CELL_PRIVATE #include "core/or/circuit_st.h" #include "core/or/or_circuit_st.h" @@ -152,26 +153,28 @@ smartlist_add(circ->sendme_last_digests, tor_memdup(digest, sizeof(digest))); /* SENDME v1 payload is 3 bytes + 20 bytes digest. See spec. */ - ret = build_cell_payload_v1(digest, payload); + ret = build_cell_payload_v1(digest, 20, payload); tt_int_op(ret, OP_EQ, 23); /* Validation. */ /* An empty payload means SENDME version 0 thus valid. */ - tt_int_op(sendme_is_valid(circ, payload, 0), OP_EQ, true); + tt_int_op(sendme_is_valid(circ, NULL, payload, 0), OP_EQ, true); /* Current phoney digest should have been popped. */ tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 0); /* An unparseable cell means invalid. */ setup_full_capture_of_logs(LOG_INFO); - tt_int_op(sendme_is_valid(circ, (const uint8_t *) "A", 1), OP_EQ, false); + tt_int_op(sendme_is_valid(circ, NULL, (const uint8_t *) "A", 1), + OP_EQ, false); expect_log_msg_containing("Unparseable SENDME cell received. " "Closing circuit."); teardown_capture_of_logs(); /* No cell digest recorded for this. */ setup_full_capture_of_logs(LOG_INFO); - tt_int_op(sendme_is_valid(circ, payload, sizeof(payload)), OP_EQ, false); + tt_int_op(sendme_is_valid(circ, NULL, payload, sizeof(payload)), + OP_EQ, false); expect_log_msg_containing("We received a SENDME but we have no cell digests " "to match. Closing circuit."); teardown_capture_of_logs(); @@ -181,18 +184,20 @@ sendme_record_cell_digest_on_circ(circ, NULL); tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1); setup_full_capture_of_logs(LOG_INFO); - tt_int_op(sendme_is_valid(circ, payload, sizeof(payload)), OP_EQ, false); + tt_int_op(sendme_is_valid(circ, NULL, payload, sizeof(payload)), + OP_EQ, false); /* After a validation, the last digests is always popped out. */ tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 0); expect_log_msg_containing("SENDME v1 cell digest do not match."); teardown_capture_of_logs(); /* Record the cell digest into the circuit, cell should validate. */ - memcpy(or_circ->crypto.sendme_digest, digest, sizeof(digest)); + memcpy(or_circ->crypto.c.tor1.sendme_digest, digest, sizeof(digest)); circ->package_window = CIRCWINDOW_INCREMENT + 1; sendme_record_cell_digest_on_circ(circ, NULL); tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1); - tt_int_op(sendme_is_valid(circ, payload, sizeof(payload)), OP_EQ, true); + tt_int_op(sendme_is_valid(circ, NULL, payload, sizeof(payload)), + OP_EQ, true); /* After a validation, the last digests is always popped out. */ tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 0); @@ -202,48 +207,6 @@ } static void -test_cell_payload_pad(void *arg) -{ - size_t pad_offset, payload_len, expected_offset; - - (void) arg; - - /* Offset should be 0, not enough room for padding. */ - payload_len = RELAY_PAYLOAD_SIZE; - pad_offset = get_pad_cell_offset(payload_len); - tt_int_op(pad_offset, OP_EQ, 0); - tt_int_op(CELL_PAYLOAD_SIZE - pad_offset, OP_LE, CELL_PAYLOAD_SIZE); - - /* Still no room because we keep 4 extra bytes. */ - pad_offset = get_pad_cell_offset(payload_len - 4); - tt_int_op(pad_offset, OP_EQ, 0); - tt_int_op(CELL_PAYLOAD_SIZE - pad_offset, OP_LE, CELL_PAYLOAD_SIZE); - - /* We should have 1 byte of padding. Meaning, the offset should be the - * CELL_PAYLOAD_SIZE minus 1 byte. */ - expected_offset = CELL_PAYLOAD_SIZE - 1; - pad_offset = get_pad_cell_offset(payload_len - 5); - tt_int_op(pad_offset, OP_EQ, expected_offset); - tt_int_op(CELL_PAYLOAD_SIZE - pad_offset, OP_LE, CELL_PAYLOAD_SIZE); - - /* Now some arbitrary small payload length. The cell size is header + 10 + - * extra 4 bytes we keep so the offset should be there. */ - expected_offset = RELAY_HEADER_SIZE + 10 + 4; - pad_offset = get_pad_cell_offset(10); - tt_int_op(pad_offset, OP_EQ, expected_offset); - tt_int_op(CELL_PAYLOAD_SIZE - pad_offset, OP_LE, CELL_PAYLOAD_SIZE); - - /* Data length of 0. */ - expected_offset = RELAY_HEADER_SIZE + 4; - pad_offset = get_pad_cell_offset(0); - tt_int_op(pad_offset, OP_EQ, expected_offset); - tt_int_op(CELL_PAYLOAD_SIZE - pad_offset, OP_LE, CELL_PAYLOAD_SIZE); - - done: - ; -} - -static void test_cell_version_validation(void *arg) { (void) arg; @@ -275,9 +238,11 @@ test_package_payload_len(void *arg) { (void)arg; - /* this is not a real circuit: it only has the fields needed for this - * test. */ - circuit_t *c = tor_malloc_zero(sizeof(circuit_t)); + or_circuit_t *or_circ = or_circuit_new(0, NULL); + crypt_path_t *cpath = NULL; + circuit_t *c = TO_CIRCUIT(or_circ); + + or_circ->relay_cell_format = RELAY_CELL_FORMAT_V0; /* check initial conditions. */ circuit_reset_sendme_randomness(c); @@ -288,15 +253,16 @@ /* We have a bunch of cells before we need to send randomness, so the first * few can be packaged full. */ int initial = c->send_randomness_after_n_cells; - size_t n = connection_edge_get_inbuf_bytes_to_package(10000, 0, c); + size_t n = connection_edge_get_inbuf_bytes_to_package(10000, 0, c, cpath); tt_uint_op(RELAY_PAYLOAD_SIZE, OP_EQ, n); - n = connection_edge_get_inbuf_bytes_to_package(95000, 1, c); + n = connection_edge_get_inbuf_bytes_to_package(95000, 1, c, cpath); tt_uint_op(RELAY_PAYLOAD_SIZE, OP_EQ, n); tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 2); /* If package_partial isn't set, we won't package a partially full cell at * all. */ - n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-1, 0, c); + n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-1, 0, + c, cpath); tt_int_op(n, OP_EQ, 0); /* no change in our state, since nothing was sent. */ tt_assert(! c->have_sent_sufficiently_random_cell); @@ -305,13 +271,15 @@ /* If package_partial is set and the partial cell is not going to have * _enough_ randomness, we package it, but we don't consider ourselves to * have sent a sufficiently random cell. */ - n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-1, 1, c); + n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-1, 1, + c, cpath); tt_int_op(n, OP_EQ, RELAY_PAYLOAD_SIZE-1); tt_assert(! c->have_sent_sufficiently_random_cell); tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 3); /* Make sure we set have_set_sufficiently_random_cell as appropriate. */ - n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-64, 1, c); + n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-64, 1, + c, cpath); tt_int_op(n, OP_EQ, RELAY_PAYLOAD_SIZE-64); tt_assert(c->have_sent_sufficiently_random_cell); tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 4); @@ -320,7 +288,7 @@ * sent a sufficiently random cell, we will not force this one to have a gap. */ c->send_randomness_after_n_cells = 0; - n = connection_edge_get_inbuf_bytes_to_package(10000, 1, c); + n = connection_edge_get_inbuf_bytes_to_package(10000, 1, c, cpath); tt_int_op(n, OP_EQ, RELAY_PAYLOAD_SIZE); /* Now these will be reset. */ tt_assert(! c->have_sent_sufficiently_random_cell); @@ -329,7 +297,7 @@ /* What would happen if we hadn't sent a sufficiently random cell? */ c->send_randomness_after_n_cells = 0; - n = connection_edge_get_inbuf_bytes_to_package(10000, 1, c); + n = connection_edge_get_inbuf_bytes_to_package(10000, 1, c, cpath); const size_t reduced_payload_size = RELAY_PAYLOAD_SIZE - 4 - 16; tt_int_op(n, OP_EQ, reduced_payload_size); /* Now these will be reset. */ @@ -341,55 +309,12 @@ * package_partial==0 should mean we accept that many bytes. */ c->send_randomness_after_n_cells = 0; - n = connection_edge_get_inbuf_bytes_to_package(reduced_payload_size, 0, c); + n = connection_edge_get_inbuf_bytes_to_package(reduced_payload_size, 0, + c, cpath); tt_int_op(n, OP_EQ, reduced_payload_size); done: - tor_free(c); -} - -/* Check that circuit_sendme_is_next works with a window of 1000, - * and a sendme_inc of 100 (old school tor compat) */ -static void -test_sendme_is_next1000(void *arg) -{ - (void)arg; - tt_int_op(circuit_sendme_cell_is_next(1000, 100), OP_EQ, 0); - tt_int_op(circuit_sendme_cell_is_next(999, 100), OP_EQ, 0); - tt_int_op(circuit_sendme_cell_is_next(901, 100), OP_EQ, 1); - - tt_int_op(circuit_sendme_cell_is_next(900, 100), OP_EQ, 0); - tt_int_op(circuit_sendme_cell_is_next(899, 100), OP_EQ, 0); - tt_int_op(circuit_sendme_cell_is_next(801, 100), OP_EQ, 1); - - tt_int_op(circuit_sendme_cell_is_next(101, 100), OP_EQ, 1); - tt_int_op(circuit_sendme_cell_is_next(100, 100), OP_EQ, 0); - tt_int_op(circuit_sendme_cell_is_next(99, 100), OP_EQ, 0); - tt_int_op(circuit_sendme_cell_is_next(1, 100), OP_EQ, 1); - tt_int_op(circuit_sendme_cell_is_next(0, 100), OP_EQ, 0); - -done: - ; -} - -/* Check that circuit_sendme_is_next works with a window of 31 */ -static void -test_sendme_is_next(void *arg) -{ - (void)arg; - tt_int_op(circuit_sendme_cell_is_next(1000, 31), OP_EQ, 0); - tt_int_op(circuit_sendme_cell_is_next(970, 31), OP_EQ, 1); - tt_int_op(circuit_sendme_cell_is_next(969, 31), OP_EQ, 0); - - /* deliver_window should never get this low, but test anyway */ - tt_int_op(circuit_sendme_cell_is_next(9, 31), OP_EQ, 1); - tt_int_op(circuit_sendme_cell_is_next(8, 31), OP_EQ, 0); - tt_int_op(circuit_sendme_cell_is_next(7, 31), OP_EQ, 0); - tt_int_op(circuit_sendme_cell_is_next(1, 31), OP_EQ, 0); - tt_int_op(circuit_sendme_cell_is_next(0, 31), OP_EQ, 0); - - done: - ; + circuit_free(c); } struct testcase_t sendme_tests[] = { @@ -399,13 +324,9 @@ NULL, NULL }, { "v1_build_cell", test_v1_build_cell, TT_FORK, NULL, NULL }, - { "cell_payload_pad", test_cell_payload_pad, TT_FORK, - NULL, NULL }, { "cell_version_validation", test_cell_version_validation, TT_FORK, NULL, NULL }, { "package_payload_len", test_package_payload_len, 0, NULL, NULL }, - { "sendme_is_next1000", test_sendme_is_next1000, 0, NULL, NULL }, - { "sendme_is_next", test_sendme_is_next, 0, NULL, NULL }, END_OF_TESTCASES }; diff -Nru tor-0.4.8.16/src/test/test_socks.c tor-0.4.9.6/src/test/test_socks.c --- tor-0.4.8.16/src/test/test_socks.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_socks.c 2026-03-25 14:30:34.000000000 +0000 @@ -596,6 +596,70 @@ ; } +/** Perform SOCKS 5 authentication and send data all in one go */ +static void +test_socks_5_authenticate_with_rpc_objectid(void *ptr) +{ + SOCKS_TEST_INIT(); + + /* SOCKS 5 Negotiate username/password authentication */ + ADD_DATA(buf, "\x05\x01\x02"); + tt_assert(!fetch_from_buf_socks(buf, socks, + get_options()->TestSocks, + get_options()->SafeSocks)); + /* SOCKS 5 Send username/password as a RPC ObjectID (see prop351). This + * should be invalid as in only the objectID prefix without a version. */ + ADD_DATA(buf, "\x01\x08\x08password"); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), OP_EQ, -1); + + buf_clear(buf); + socks_request_clear(socks); + + /* SOCKS 5 Negotiate username/password authentication */ + ADD_DATA(buf, "\x05\x01\x02"); + tt_assert(!fetch_from_buf_socks(buf, socks, + get_options()->TestSocks, + get_options()->SafeSocks)); + /* SOCKS 5 Send username/password as a RPC ObjectID (see prop351). This + * should be valid because it is exactly the prefix and version without an + * object ID. */ + ADD_DATA(buf, "\x01\x090\x08password"); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), OP_EQ, 0); + + buf_clear(buf); + socks_request_clear(socks); + + /* SOCKS 5 Negotiate username/password authentication */ + ADD_DATA(buf, "\x05\x01\x02"); + tt_assert(!fetch_from_buf_socks(buf, socks, + get_options()->TestSocks, + get_options()->SafeSocks)); + /* SOCKS 5 Send username/password as a RPC ObjectID (see prop351). This + * should be invalid as an unknown version per prop351. */ + ADD_DATA(buf, "\x01\x091\x08password"); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), OP_EQ, -1); + + buf_clear(buf); + socks_request_clear(socks); + + /* SOCKS 5 Negotiate username/password authentication */ + ADD_DATA(buf, "\x05\x01\x02"); + tt_assert(!fetch_from_buf_socks(buf, socks, + get_options()->TestSocks, + get_options()->SafeSocks)); + /* SOCKS 5 Send username/password as a RPC ObjectID (see prop351). This + * should be invalid because there is an objectID after the prefix. */ + ADD_DATA(buf, "\x01\x0C0abc\x08password"); + tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), OP_EQ, -1); + + done: + ; +} + /** Try to negotiate an unsupported authentication type */ static void test_socks_5_auth_unsupported_type(void *ptr) @@ -1112,6 +1176,7 @@ SOCKSENT(5_authenticate), SOCKSENT(5_authenticate_empty_user_pass), SOCKSENT(5_authenticate_with_data), + SOCKSENT(5_authenticate_with_rpc_objectid), SOCKSENT(5_malformed_commands), SOCKSENT(5_bad_arguments), diff -Nru tor-0.4.8.16/src/test/test_status.c tor-0.4.9.6/src/test/test_status.c --- tor-0.4.8.16/src/test/test_status.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_status.c 2026-03-25 14:30:34.000000000 +0000 @@ -333,10 +333,12 @@ status_hb_not_in_consensus_server_mode); log_global_min_severity_ = LOG_DEBUG; - onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP] = 1; onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_TAP] = 1; - onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR] = 1; - onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR] = 1; + onion_handshakes_requested[ONION_HANDSHAKE_TYPE_TAP] = 2; + onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR] = 3; + onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR] = 4; + onion_handshakes_assigned[ONION_HANDSHAKE_TYPE_NTOR_V3] = 5; + onion_handshakes_requested[ONION_HANDSHAKE_TYPE_NTOR_V3] = 6; expected = 0; setup_capture_of_logs(LOG_INFO); @@ -352,8 +354,8 @@ "I've made 0 connections with IPv4 and 0 with IPv6.\n"); expect_log_msg("Average packaged cell fullness: 100.000%. " "TLS write overhead: 0%\n"); - expect_log_msg("Circuit handshake stats since last time: 1/1 TAP, " - "1/1 NTor.\n"); + expect_log_msg("Circuit handshake stats since last time: 1/2 TAP, " + "3/4 NTor, 5/6 NTor (v3).\n"); expect_log_msg("Since startup we initiated 0 and received 0 v1 " "connections; initiated 0 and received 0 v2 connections; " "initiated 0 and received 0 v3 connections; " @@ -363,6 +365,7 @@ "with too many cells, [DoSCircuitCreationEnabled disabled], " "[DoSConnectionEnabled disabled], " "[DoSRefuseSingleHopClientRendezvous disabled], " + "[DoSStreamCreationEnabled disabled], " "0 INTRODUCE2 rejected.\n"); tt_int_op(mock_saved_log_n_entries(), OP_EQ, 6); diff -Nru tor-0.4.8.16/src/test/test_tortls.c tor-0.4.9.6/src/test/test_tortls.c --- tor-0.4.8.16/src/test/test_tortls.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_tortls.c 2026-03-25 14:30:34.000000000 +0000 @@ -49,62 +49,80 @@ "evnAhf0cwULaebn+lMs8Pdl7y37+sfluVok=\n" "-----END CERTIFICATE-----\n"; -const char* validCertString = "-----BEGIN CERTIFICATE-----\n" - "MIIDpTCCAY0CAg3+MA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNVBAYTAlVTMREwDwYD\n" - "VQQIDAhJbGxpbm9pczEQMA4GA1UEBwwHQ2hpY2FnbzEUMBIGA1UECgwLVG9yIFRl\n" - "c3RpbmcxFDASBgNVBAMMC1RvciBUZXN0aW5nMB4XDTE1MDkwNjEzMzk1OVoXDTQz\n" - "MDEyMjEzMzk1OVowVjELMAkGA1UEBhMCVVMxEDAOBgNVBAcMB0NoaWNhZ28xFDAS\n" - "BgNVBAoMC1RvciBUZXN0aW5nMR8wHQYDVQQDDBZ0ZXN0aW5nLnRvcnByb2plY3Qu\n" - "b3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoT6uyVVhWyOF3wkHjjYbd\n" - "nKaykyRv4JVtKQdZ4OpEErmX1zw4MmyzpQNV6iR4bQnWiyLfzyVJMZDIC/WILBfX\n" - "w2Pza/yuLgUvDc3twMuhOACzOQVO8PrEF/aVv2+hbCCy2udXvKhnYn+CCXl3ozc8\n" - "XcKYvujTXDyvGWY3xwAjlQIDAQABMA0GCSqGSIb3DQEBBQUAA4ICAQCUvnhzQWuQ\n" - "MrN+pERkE+zcTI/9dGS90rUMMLgu8VDNqTa0TUQh8uO0EQ6uDvI8Js6e8tgwS0BR\n" - "UBahqb7ZHv+rejGCBr5OudqD+x4STiiuPNJVs86JTLN8SpM9CHjIBH5WCCN2KOy3\n" - "mevNoRcRRyYJzSFULCunIK6FGulszigMYGscrO4oiTkZiHPh9KvWT40IMiHfL+Lw\n" - "EtEWiLex6064LcA2YQ1AMuSZyCexks63lcfaFmQbkYOKqXa1oLkIRuDsOaSVjTfe\n" - "vec+X6jvf12cFTKS5WIeqkKF2Irt+dJoiHEGTe5RscUMN/f+gqHPzfFz5dR23sxo\n" - "g+HC6MZHlFkLAOx3wW6epPS8A/m1mw3zMPoTnb2U2YYt8T0dJMMlUn/7Y1sEAa+a\n" - "dSTMaeUf6VnJ//11m454EZl1to9Z7oJOgqmFffSrdD4BGIWe8f7hhW6L1Enmqe/J\n" - "BKL3wbzZh80O1W0bndAwhnEEhlzneFY84cbBo9pmVxpODHkUcStpr5Z7pBDrcL21\n" - "Ss/aB/1YrsVXhdvJdOGxl3Mnl9dUY57CympLGlT8f0pPS6GAKOelECOhFMHmJd8L\n" - "dj3XQSmKtYHevZ6IvuMXSlB/fJvSjSlkCuLo5+kJoaqPuRu+i/S1qxeRy3CBwmnE\n" - "LdSNdcX4N79GQJ996PA8+mUCQG7YRtK+WA==\n" +// Tor www.torproject.org certificate. +// Fetched March 6 2025, ~1320 UTC. +const char* validCertString = + "-----BEGIN CERTIFICATE-----\n" + "MIIF8zCCBNugAwIBAgISBMmLkAm3fEUb8UQC5EdseU8ZMA0GCSqGSIb3DQEBCwUA\n" + "MDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQD\n" + "EwNSMTAwHhcNMjUwMTMwMDA1MTU0WhcNMjUwNDMwMDA1MTUzWjAdMRswGQYDVQQD\n" + "ExJ3d3cudG9ycHJvamVjdC5vcmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK\n" + "AoICAQDGG3XaG3ZB5QbJisjUbyBW+dgoZy2E3dJ0qMaWyO3/dB8yz4gKKMFCr1Gj\n" + "xjcfWYiayN1mcL8/QWOiD8x1s25FHeWBoDpyHX70TlRK6ZL1u2imsgoIiNaOh7f6\n" + "zfY7EQHu5UTuwSF9xBVf6FGuJ1b+ZGfXE5dBg3JJ78E8unT+xz6TUzEBUHRF7mgR\n" + "nGSgy2vqTT2EpoGq2ZioV8v8JrjkLFUx40XimUPphBs0vdY+gzVCp2wKHRgxglAD\n" + "ut3UzLLs7dW/JV9OSSj5L46CQwuaC5xjGEBcarS202oyBdC7DZpolHVKmwJd6IOj\n" + "DcachL3VFDGPXQe3/TVcale8y6mfhYbGYn8v9SpeHOdsWv5kCNCpHaHYmdSCiCFG\n" + "lmFxnuisu74WghiLrHeHB3oydjACQOyJ4d3u1P9oFKqxPX4ui3ACVWcvksNVQSmR\n" + "LlLE2SrK9wIwn2oNs5jJuR68yMV57i20TGvqBSsCZ3m99glpXwG50tzgqfBwFFDX\n" + "QElJWI8GQvKQIh43TYBvpZXYIG9srvGdl9eUCNXTFhGosc0+sfKoPpUf7f0R58pj\n" + "fjdyDyXb+M6Z60mflOeUM+UR9Q5VeTJ69IfpLypC2JaHy2HCuNekvkbB7TuPuvC9\n" + "vANjovgo5zI3MAcp2v9Y6EDgeScKMbZBQM6nuljvw9npaqkHXQIDAQABo4ICFTCC\n" + "AhEwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD\n" + "AjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRWG7Q4+uqENJPVGkL74DH+LCrhjzAf\n" + "BgNVHSMEGDAWgBS7vMNHpeS8qcbDpHIMEI2iNeHI6DBXBggrBgEFBQcBAQRLMEkw\n" + "IgYIKwYBBQUHMAGGFmh0dHA6Ly9yMTAuby5sZW5jci5vcmcwIwYIKwYBBQUHMAKG\n" + "F2h0dHA6Ly9yMTAuaS5sZW5jci5vcmcvMB0GA1UdEQQWMBSCEnd3dy50b3Jwcm9q\n" + "ZWN0Lm9yZzATBgNVHSAEDDAKMAgGBmeBDAECATCCAQMGCisGAQQB1nkCBAIEgfQE\n" + "gfEA7wB1AMz7D2qFcQll/pWbU87psnwi6YVcDZeNtql+VMD+TA2wAAABlLTm/wYA\n" + "AAQDAEYwRAIgHWbnkMLOUDDJg7vog3J66Aa2wuRYg4DFS21uUtPVUQgCIFZhio8Z\n" + "CQcZsdFpeGzAUjXcyboVrvdMg3/3jwWgdQ82AHYA5tIxY0B3jMEQQQbXcbnOwdJA\n" + "9paEhvu6hzId/R43jlAAAAGUtOb/DQAABAMARzBFAiBHNO8CjQdQcMENnXyH5oBL\n" + "kfdZghUHzMEfFKlg5p+QDAIhAP0dEqz+Q2A2XCvN09vZJ1gsG8IzQELHpBM8QDyM\n" + "KSavMA0GCSqGSIb3DQEBCwUAA4IBAQDNh8KjUWJKio63zn2JrFlpIsnrVchPP+ee\n" + "1XUrHQt/BA1pUdlTFPQrHOCf6KOGpiyjXxKkBdtJvc/5ZJZYJ26E6Ytd0nGOCirE\n" + "v0W45Vh22rH1w0Q1fH1xOqZx1qeh4QYr1/QJ3gWWMTOH5uV5dTzK9RWfp0C1pjQ6\n" + "Rct/0ZqyZHYqMD9VoAiVap7lwnWNWOj+UEioH2cMqjCkD5g8QGNHEfereB3DtoV3\n" + "Qw1Z3KoUEr2zEDfq+Uv6RLKCw3HjzDYKbHWSYkrUO7YyIQ3nlZAT861478k5WSKv\n" + "hpy8XisMLpQLAhSByV965gINlmHXbe61anJUh3JJpnOu/JyMfaf/\n" "-----END CERTIFICATE-----\n"; -const char* caCertString = "-----BEGIN CERTIFICATE-----\n" - "MIIFjzCCA3egAwIBAgIJAKd5WgyfPMYRMA0GCSqGSIb3DQEBCwUAMF4xCzAJBgNV\n" - "BAYTAlVTMREwDwYDVQQIDAhJbGxpbm9pczEQMA4GA1UEBwwHQ2hpY2FnbzEUMBIG\n" - "A1UECgwLVG9yIFRlc3RpbmcxFDASBgNVBAMMC1RvciBUZXN0aW5nMB4XDTE1MDkw\n" - "NjEzMzc0MVoXDTQzMDEyMjEzMzc0MVowXjELMAkGA1UEBhMCVVMxETAPBgNVBAgM\n" - "CElsbGlub2lzMRAwDgYDVQQHDAdDaGljYWdvMRQwEgYDVQQKDAtUb3IgVGVzdGlu\n" - "ZzEUMBIGA1UEAwwLVG9yIFRlc3RpbmcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw\n" - "ggIKAoICAQCpLMUEiLW5leUgBZoEJms2V7lZRhIAjnJBhVMHD0e3UubNknmaQoxf\n" - "ARz3rvqOaRd0JlV+qM9qE0DjiYcCVP1cAfqAo9d83uS1vwY3YMVJzADlaIiHfyVW\n" - "uEgBy0vvkeUBqaua24dYlcwsemOiXYLu41yM1wkcGHW1AhBNHppY6cznb8TyLgNM\n" - "2x3SGUdzc5XMyAFx51faKGBA3wjs+Hg1PLY7d30nmCgEOBavpm5I1disM/0k+Mcy\n" - "YmAKEo/iHJX/rQzO4b9znP69juLlR8PDBUJEVIG/CYb6+uw8MjjUyiWXYoqfVmN2\n" - "hm/lH8b6rXw1a2Aa3VTeD0DxaWeacMYHY/i01fd5n7hCoDTRNdSw5KJ0L3Z0SKTu\n" - "0lzffKzDaIfyZGlpW5qdouACkWYzsaitQOePVE01PIdO30vUfzNTFDfy42ccx3Di\n" - "59UCu+IXB+eMtrBfsok0Qc63vtF1linJgjHW1z/8ujk8F7/qkOfODhk4l7wngc2A\n" - "EmwWFIFoGaiTEZHB9qteXr4unbXZ0AHpM02uGGwZEGohjFyebEb73M+J57WKKAFb\n" - "PqbLcGUksL1SHNBNAJcVLttX55sO4nbidOS/kA3m+F1R04MBTyQF9qA6YDDHqdI3\n" - "h/3pw0Z4fxVouTYT4/NfRnX4JTP4u+7Mpcoof28VME0qWqD1LnRhFQIDAQABo1Aw\n" - "TjAdBgNVHQ4EFgQUMoAgIXH7pZ3QMRwTjT+DM9Yo/v0wHwYDVR0jBBgwFoAUMoAg\n" - "IXH7pZ3QMRwTjT+DM9Yo/v0wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC\n" - "AgEAUJxacjXR9sT+Xs6ISFiUsyd0T6WVKMnV46xrYJHirGfx+krWHrjxMY+ZtxYD\n" - "DBDGlo11Qc4v6QrclNf5QUBfIiGQsP9Cm6hHcQ+Tpg9HHCgSqG1YNPwCPReCR4br\n" - "BLvLfrfkcBL2IWM0PdQdCze+59DBfipsULD2mEn9fjYRXQEwb2QWtQ9qRc20Yb/x\n" - "Q4b/+CvUodLkaq7B8MHz0BV8HHcBoph6DYaRmO/N+hPauIuSp6XyaGYcEefGKVKj\n" - "G2+fcsdyXsoijNdL8vNKwm4j2gVwCBnw16J00yfFoV46YcbfqEdJB2je0XSvwXqt\n" - "14AOTngxso2h9k9HLtrfpO1ZG/B5AcCMs1lzbZ2fp5DPHtjvvmvA2RJqgo3yjw4W\n" - "4DHAuTglYFlC3mDHNfNtcGP20JvepcQNzNP2UzwcpOc94hfKikOFw+gf9Vf1qd0y\n" - "h/Sk6OZHn2+JVUPiWHIQV98Vtoh4RmUZDJD+b55ia3fQGTGzt4z1XFzQYSva5sfs\n" - "wocS/papthqWldQU7x+3wofNd5CNU1x6WKXG/yw30IT/4F8ADJD6GeygNT8QJYvt\n" - "u/8lAkbOy6B9xGmSvr0Kk1oq9P2NshA6kalxp1Oz/DTNDdL4AeBXV3JmM6WWCjGn\n" - "Yy1RT69d0rwYc5u/vnqODz1IjvT90smsrkBumGt791FAFeg=\n" +// Let's encrypt certificate, used to sign validCertString. +// Also fetched March 6 2025, ~1320 UTC. +const char* caCertString = + "-----BEGIN CERTIFICATE-----\n" + "MIIFBTCCAu2gAwIBAgIQS6hSk/eaL6JzBkuoBI110DANBgkqhkiG9w0BAQsFADBP\n" + "MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy\n" + "Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa\n" + "Fw0yNzAzMTIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF\n" + "bmNyeXB0MQwwCgYDVQQDEwNSMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\n" + "AoIBAQDPV+XmxFQS7bRH/sknWHZGUCiMHT6I3wWd1bUYKb3dtVq/+vbOo76vACFL\n" + "YlpaPAEvxVgD9on/jhFD68G14BQHlo9vH9fnuoE5CXVlt8KvGFs3Jijno/QHK20a\n" + "/6tYvJWuQP/py1fEtVt/eA0YYbwX51TGu0mRzW4Y0YCF7qZlNrx06rxQTOr8IfM4\n" + "FpOUurDTazgGzRYSespSdcitdrLCnF2YRVxvYXvGLe48E1KGAdlX5jgc3421H5KR\n" + "mudKHMxFqHJV8LDmowfs/acbZp4/SItxhHFYyTr6717yW0QrPHTnj7JHwQdqzZq3\n" + "DZb3EoEmUVQK7GH29/Xi8orIlQ2NAgMBAAGjgfgwgfUwDgYDVR0PAQH/BAQDAgGG\n" + "MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/\n" + "AgEAMB0GA1UdDgQWBBS7vMNHpeS8qcbDpHIMEI2iNeHI6DAfBgNVHSMEGDAWgBR5\n" + "tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKG\n" + "Fmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0gBAwwCjAIBgZngQwBAgEwJwYD\n" + "VR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVuY3Iub3JnLzANBgkqhkiG9w0B\n" + "AQsFAAOCAgEAkrHnQTfreZ2B5s3iJeE6IOmQRJWjgVzPw139vaBw1bGWKCIL0vIo\n" + "zwzn1OZDjCQiHcFCktEJr59L9MhwTyAWsVrdAfYf+B9haxQnsHKNY67u4s5Lzzfd\n" + "u6PUzeetUK29v+PsPmI2cJkxp+iN3epi4hKu9ZzUPSwMqtCceb7qPVxEbpYxY1p9\n" + "1n5PJKBLBX9eb9LU6l8zSxPWV7bK3lG4XaMJgnT9x3ies7msFtpKK5bDtotij/l0\n" + "GaKeA97pb5uwD9KgWvaFXMIEt8jVTjLEvwRdvCn294GPDF08U8lAkIv7tghluaQh\n" + "1QnlE4SEN4LOECj8dsIGJXpGUk3aU3KkJz9icKy+aUgA+2cP21uh6NcDIS3XyfaZ\n" + "QjmDQ993ChII8SXWupQZVBiIpcWO4RqZk3lr7Bz5MUCwzDIA359e57SSq5CCkY0N\n" + "4B6Vulk7LktfwrdGNVI5BsC9qqxSwSKgRJeZ9wygIaehbHFHFhcBaMDKpiZlBHyz\n" + "rsnnlFXCb5s8HKn5LsUgGvB24L7sGNZP2CX7dhHov+YhD+jozLW2p9W4959Bz2Ei\n" + "RmqDtmiXLnzqTpXbI+suyCsohKRg6Un0RC47+cpiVwHiXZAW+cn8eiNIjqbVgXLx\n" + "KPpdzvvtTnOPlC7SQZSYmdunr3Bf9b77AiC/ZidstK36dRILKz7OA54=\n" "-----END CERTIFICATE-----\n"; +// A time at which the certs above are valid. +const time_t cert_strings_valid_at = 1741267580; + static tor_x509_cert_t *fixed_x509_cert = NULL; static tor_x509_cert_t * get_peer_cert_mock_return_fixed(tor_tls_t *tls) @@ -136,24 +154,6 @@ return res; } -static tor_x509_cert_impl_t * - fixed_try_to_extract_certs_from_tls_cert_out_result = NULL; -static tor_x509_cert_impl_t * - fixed_try_to_extract_certs_from_tls_id_cert_out_result = NULL; - -static void -fixed_try_to_extract_certs_from_tls(int severity, tor_tls_t *tls, - tor_x509_cert_impl_t **cert_out, - tor_x509_cert_impl_t **id_cert_out) -{ - (void) severity; - (void) tls; - *cert_out = tor_x509_cert_impl_dup_( - fixed_try_to_extract_certs_from_tls_cert_out_result); - *id_cert_out = tor_x509_cert_impl_dup_( - fixed_try_to_extract_certs_from_tls_id_cert_out_result); -} - static void test_tortls_errno_to_tls_error(void *data) { @@ -309,44 +309,6 @@ done: tor_free(tls); } - -static void -test_tortls_used_v1_handshake(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - tls = tor_malloc_zero(sizeof(tor_tls_t)); - - // These tests assume both V2 handshake server and client are enabled - tls->wasV2Handshake = 0; - ret = tor_tls_used_v1_handshake(tls); - tt_int_op(ret, OP_EQ, 1); - - tls->wasV2Handshake = 1; - ret = tor_tls_used_v1_handshake(tls); - tt_int_op(ret, OP_EQ, 0); - - done: - tor_free(tls); -} - -static void -test_tortls_server_got_renegotiate(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - - tls->got_renegotiate = 1; - ret = tor_tls_server_got_renegotiate(tls); - tt_int_op(ret, OP_EQ, 1); - - done: - tor_free(tls); -} #endif /* defined(ENABLE_OPENSSL) */ static void @@ -474,57 +436,6 @@ } static void -test_tortls_verify(void *ignored) -{ - (void)ignored; - int ret; - tor_tls_t *tls; - crypto_pk_t *k = NULL; - tor_x509_cert_impl_t *cert1 = NULL, *cert2 = NULL, *invalidCert = NULL, - *validCert = NULL, *caCert = NULL; - - validCert = read_cert_from(validCertString); - caCert = read_cert_from(caCertString); - invalidCert = read_cert_from(notCompletelyValidCertString); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - - MOCK(try_to_extract_certs_from_tls, fixed_try_to_extract_certs_from_tls); - - fixed_try_to_extract_certs_from_tls_cert_out_result = cert1; - ret = tor_tls_verify(LOG_WARN, tls, &k); - tt_int_op(ret, OP_EQ, -1); - - fixed_try_to_extract_certs_from_tls_id_cert_out_result = cert2; - ret = tor_tls_verify(LOG_WARN, tls, &k); - tt_int_op(ret, OP_EQ, -1); - - fixed_try_to_extract_certs_from_tls_cert_out_result = invalidCert; - fixed_try_to_extract_certs_from_tls_id_cert_out_result = invalidCert; - - ret = tor_tls_verify(LOG_WARN, tls, &k); - tt_int_op(ret, OP_EQ, -1); - - fixed_try_to_extract_certs_from_tls_cert_out_result = validCert; - fixed_try_to_extract_certs_from_tls_id_cert_out_result = caCert; - - ret = tor_tls_verify(LOG_WARN, tls, &k); - tt_int_op(ret, OP_EQ, 0); - tt_assert(k); - - done: - UNMOCK(try_to_extract_certs_from_tls); - tor_x509_cert_impl_free(cert1); - tor_x509_cert_impl_free(cert2); - tor_x509_cert_impl_free(validCert); - tor_x509_cert_impl_free(invalidCert); - tor_x509_cert_impl_free(caCert); - - tor_free(tls); - crypto_pk_free(k); -} - -static void test_tortls_cert_matches_key(void *ignored) { (void)ignored; @@ -596,15 +507,12 @@ #ifdef ENABLE_OPENSSL LOCAL_TEST_CASE(tor_tls_get_error, 0), LOCAL_TEST_CASE(get_forced_write_size, 0), - LOCAL_TEST_CASE(used_v1_handshake, TT_FORK), - LOCAL_TEST_CASE(server_got_renegotiate, 0), #endif /* defined(ENABLE_OPENSSL) */ LOCAL_TEST_CASE(evaluate_ecgroup_for_tls, 0), LOCAL_TEST_CASE(double_init, TT_FORK), LOCAL_TEST_CASE(address, TT_FORK), LOCAL_TEST_CASE(is_server, 0), LOCAL_TEST_CASE(bridge_init, TT_FORK), - LOCAL_TEST_CASE(verify, TT_FORK), LOCAL_TEST_CASE(cert_matches_key, 0), END_OF_TESTCASES }; diff -Nru tor-0.4.8.16/src/test/test_tortls.h tor-0.4.9.6/src/test/test_tortls.h --- tor-0.4.8.16/src/test/test_tortls.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_tortls.h 2026-03-25 14:30:34.000000000 +0000 @@ -9,5 +9,6 @@ extern const char *notCompletelyValidCertString; extern const char *validCertString; extern const char *caCertString; +extern const time_t cert_strings_valid_at; #endif /* !defined(TEST_TORTLS_H) */ diff -Nru tor-0.4.8.16/src/test/test_tortls_openssl.c tor-0.4.9.6/src/test/test_tortls_openssl.c --- tor-0.4.8.16/src/test/test_tortls_openssl.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_tortls_openssl.c 2026-03-25 14:30:34.000000000 +0000 @@ -46,15 +46,19 @@ #include "test/log_test_helpers.h" #include "test/test_tortls.h" -#ifndef HAVE_SSL_STATE -#define OPENSSL_OPAQUE -#endif - -#if defined(OPENSSL_OPAQUE) && !defined(LIBRESSL_VERSION_NUMBER) #define SSL_STATE_STR "before SSL initialization" -#else -#define SSL_STATE_STR "before/accept initialization" -#endif + +/* Every version and fork of OpenSSL we support now qualifies as "opaque", + * in that it hides the members of important structures. + * + * That's a good thing, but it means we can't run a number of older tests + * that require the ability to poke at OpenSSL's internals. + * + * We're retaining these tests here, rather than removing them, + * in case anybody wants to port them to modern OpenSSL. + * (Some of them are probably not worth saving, though.) + */ +#define OPENSSL_OPAQUE #ifndef OPENSSL_OPAQUE static SSL_METHOD * @@ -124,12 +128,7 @@ static void library_init(void) { -#ifdef OPENSSL_1_1_API OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); -#else - SSL_library_init(); - SSL_load_error_strings(); -#endif /* defined(OPENSSL_1_1_API) */ } static void @@ -296,13 +295,6 @@ LOG_WARN, 0, NULL); expect_log_severity(LOG_INFO); -#ifndef OPENSSL_1_1_API - mock_clean_saved_logs(); - tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_RECORD_TOO_LARGE), - LOG_WARN, 0, NULL); - expect_log_severity(LOG_INFO); -#endif /* !defined(OPENSSL_1_1_API) */ - mock_clean_saved_logs(); tor_tls_log_one_error(tls, ERR_PACK(1, 2, SSL_R_UNKNOWN_PROTOCOL), LOG_WARN, 0, NULL); @@ -505,232 +497,6 @@ } #endif /* !defined(OPENSSL_OPAQUE) */ -static void -test_tortls_get_my_client_auth_key(void *ignored) -{ - (void)ignored; - crypto_pk_t *ret; - crypto_pk_t *expected; - tor_tls_context_t *ctx; - RSA *k = RSA_new(); - - ctx = tor_malloc_zero(sizeof(tor_tls_context_t)); - expected = crypto_new_pk_from_openssl_rsa_(k); - ctx->auth_key = expected; - - client_tls_context = NULL; - ret = tor_tls_get_my_client_auth_key(); - tt_assert(!ret); - - client_tls_context = ctx; - ret = tor_tls_get_my_client_auth_key(); - tt_assert(ret == expected); - - done: - crypto_pk_free(expected); - tor_free(ctx); -} - -#ifndef HAVE_SSL_GET_CLIENT_CIPHERS -static SSL_CIPHER * -get_cipher_by_name(const char *name) -{ - int i; - const SSL_METHOD *method = SSLv23_method(); - int num = method->num_ciphers(); - - for (i = 0; i < num; ++i) { - const SSL_CIPHER *cipher = method->get_cipher(i); - const char *ciphername = SSL_CIPHER_get_name(cipher); - if (!strcmp(ciphername, name)) { - return (SSL_CIPHER *)cipher; - } - } - - return NULL; -} -#endif /* !defined(HAVE_SSL_GET_CLIENT_CIPHERS) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_get_ciphersuite_name(void *ignored) -{ - (void)ignored; - const char *ret; - tor_tls_t *ctx; - ctx = tor_malloc_zero(sizeof(tor_tls_t)); - ctx->ssl = tor_malloc_zero(sizeof(SSL)); - - ret = tor_tls_get_ciphersuite_name(ctx); - tt_str_op(ret, OP_EQ, "(NONE)"); - - done: - tor_free(ctx->ssl); - tor_free(ctx); -} - -static SSL_CIPHER * -get_cipher_by_id(uint16_t id) -{ - int i; - const SSL_METHOD *method = SSLv23_method(); - int num = method->num_ciphers(); - for (i = 0; i < num; ++i) { - const SSL_CIPHER *cipher = method->get_cipher(i); - if (id == (SSL_CIPHER_get_id(cipher) & 0xffff)) { - return (SSL_CIPHER *)cipher; - } - } - - return NULL; -} - -static void -test_tortls_classify_client_ciphers(void *ignored) -{ - (void)ignored; - int i; - int ret; - SSL_CTX *ctx; - SSL *ssl; - tor_tls_t *tls; - STACK_OF(SSL_CIPHER) *ciphers; - SSL_CIPHER *tmp_cipher; - - library_init(); - - tor_tls_allocate_tor_tls_object_ex_data_index(); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->magic = TOR_TLS_MAGIC; - - ctx = SSL_CTX_new(TLSv1_method()); - ssl = SSL_new(ctx); - tls->ssl = ssl; - - ciphers = sk_SSL_CIPHER_new_null(); - - ret = tor_tls_classify_client_ciphers(ssl, NULL); - tt_int_op(ret, OP_EQ, -1); - - SSL_set_ex_data(ssl, tor_tls_object_ex_data_index, tls); - tls->client_cipher_list_type = 42; - - ret = tor_tls_classify_client_ciphers(ssl, NULL); - tt_int_op(ret, OP_EQ, 42); - - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, ciphers); - tt_int_op(ret, OP_EQ, 1); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 1); - - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, SSL_get_ciphers(ssl)); - tt_int_op(ret, OP_EQ, 3); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 3); - - SSL_CIPHER *one = get_cipher_by_name(TLS1_TXT_DHE_RSA_WITH_AES_128_SHA), - *two = get_cipher_by_name(TLS1_TXT_DHE_RSA_WITH_AES_256_SHA), - *three = get_cipher_by_name(SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA), - *four = NULL; - sk_SSL_CIPHER_push(ciphers, one); - sk_SSL_CIPHER_push(ciphers, two); - sk_SSL_CIPHER_push(ciphers, three); - sk_SSL_CIPHER_push(ciphers, four); - - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, ciphers); - tt_int_op(ret, OP_EQ, 1); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 1); - - sk_SSL_CIPHER_zero(ciphers); - - one = get_cipher_by_name("ECDHE-RSA-AES256-GCM-SHA384"); - tt_assert(one); - one->id = 0x00ff; - two = get_cipher_by_name("ECDHE-RSA-AES128-GCM-SHA256"); - tt_assert(two); - two->id = 0x0000; - sk_SSL_CIPHER_push(ciphers, one); - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, ciphers); - tt_int_op(ret, OP_EQ, 3); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 3); - - sk_SSL_CIPHER_push(ciphers, two); - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, ciphers); - tt_int_op(ret, OP_EQ, 3); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 3); - - one->id = 0xC00A; - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, ciphers); - tt_int_op(ret, OP_EQ, 3); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 3); - - sk_SSL_CIPHER_zero(ciphers); - for (i=0; v2_cipher_list[i]; i++) { - tmp_cipher = get_cipher_by_id(v2_cipher_list[i]); - tt_assert(tmp_cipher); - sk_SSL_CIPHER_push(ciphers, tmp_cipher); - } - tls->client_cipher_list_type = 0; - ret = tor_tls_classify_client_ciphers(ssl, ciphers); - tt_int_op(ret, OP_EQ, 2); - tt_int_op(tls->client_cipher_list_type, OP_EQ, 2); - - done: - sk_SSL_CIPHER_free(ciphers); - SSL_free(tls->ssl); - tor_free(tls); - SSL_CTX_free(ctx); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -static void -test_tortls_client_is_using_v2_ciphers(void *ignored) -{ - (void)ignored; - -#ifdef HAVE_SSL_GET_CLIENT_CIPHERS - tt_skip(); - done: - (void)1; -#else - int ret; - SSL_CTX *ctx; - SSL *ssl; - SSL_SESSION *sess; - STACK_OF(SSL_CIPHER) *ciphers; - - library_init(); - - ctx = SSL_CTX_new(TLSv1_method()); - ssl = SSL_new(ctx); - sess = SSL_SESSION_new(); - - ret = tor_tls_client_is_using_v2_ciphers(ssl); - tt_int_op(ret, OP_EQ, -1); - - ssl->session = sess; - ret = tor_tls_client_is_using_v2_ciphers(ssl); - tt_int_op(ret, OP_EQ, 0); - - ciphers = sk_SSL_CIPHER_new_null(); - SSL_CIPHER *one = get_cipher_by_name("ECDHE-RSA-AES256-GCM-SHA384"); - tt_assert(one); - one->id = 0x00ff; - sk_SSL_CIPHER_push(ciphers, one); - sess->ciphers = ciphers; - ret = tor_tls_client_is_using_v2_ciphers(ssl); - tt_int_op(ret, OP_EQ, 1); - done: - SSL_free(ssl); - SSL_CTX_free(ctx); -#endif /* defined(HAVE_SSL_GET_CLIENT_CIPHERS) */ -} - #ifndef OPENSSL_OPAQUE static int fixed_ssl_pending_result = 0; @@ -768,65 +534,6 @@ #ifndef OPENSSL_OPAQUE static void -test_tortls_SSL_SESSION_get_master_key(void *ignored) -{ - (void)ignored; - size_t ret; - tor_tls_t *tls; - uint8_t *out; - out = tor_malloc_zero(1); - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); - tls->ssl->session->master_key_length = 1; - -#ifndef HAVE_SSL_SESSION_GET_MASTER_KEY - tls->ssl->session->master_key[0] = 43; - ret = SSL_SESSION_get_master_key(tls->ssl->session, out, 0); - tt_int_op(ret, OP_EQ, 1); - tt_int_op(out[0], OP_EQ, 0); - - ret = SSL_SESSION_get_master_key(tls->ssl->session, out, 1); - tt_int_op(ret, OP_EQ, 1); - tt_int_op(out[0], OP_EQ, 43); - - done: -#endif /* !defined(HAVE_SSL_SESSION_GET_MASTER_KEY) */ - tor_free(tls->ssl->session); - tor_free(tls->ssl); - tor_free(tls); - tor_free(out); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_get_tlssecrets(void *ignored) -{ - (void)ignored; - int ret; - uint8_t *secret_out = tor_malloc_zero(DIGEST256_LEN); - tor_tls_t *tls; - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); - tls->ssl->session->master_key_length = 1; - tls->ssl->s3 = tor_malloc_zero(sizeof(SSL3_STATE)); - - ret = tor_tls_get_tlssecrets(tls, secret_out); - tt_int_op(ret, OP_EQ, 0); - - done: - tor_free(secret_out); - tor_free(tls->ssl->s3); - tor_free(tls->ssl->session); - tor_free(tls->ssl); - tor_free(tls); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static void test_tortls_get_buffer_sizes(void *ignored) { (void)ignored; @@ -849,23 +556,7 @@ tls->ssl->s3->wbuf.left = 43; ret = tor_tls_get_buffer_sizes(tls, &rbuf_c, &rbuf_b, &wbuf_c, &wbuf_b); -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) tt_int_op(ret, OP_EQ, -1); -#else - tt_int_op(ret, OP_EQ, 0); - tt_int_op(rbuf_c, OP_EQ, 0); - tt_int_op(wbuf_c, OP_EQ, 0); - tt_int_op(rbuf_b, OP_EQ, 42); - tt_int_op(wbuf_b, OP_EQ, 43); - - tls->ssl->s3->rbuf.buf = tor_malloc_zero(1); - tls->ssl->s3->wbuf.buf = tor_malloc_zero(1); - ret = tor_tls_get_buffer_sizes(tls, &rbuf_c, &rbuf_b, &wbuf_c, &wbuf_b); - tt_int_op(ret, OP_EQ, 0); - tt_int_op(rbuf_c, OP_EQ, 1); - tt_int_op(wbuf_c, OP_EQ, 2); - -#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) */ done: tor_free(tls->ssl->s3->rbuf.buf); @@ -877,76 +568,6 @@ #endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE -typedef struct cert_pkey_st_local -{ - X509 *x509; - EVP_PKEY *privatekey; - const EVP_MD *digest; -} CERT_PKEY_local; - -typedef struct sess_cert_st_local -{ - STACK_OF(X509) *cert_chain; - int peer_cert_type; - CERT_PKEY_local *peer_key; - CERT_PKEY_local peer_pkeys[8]; - int references; -} SESS_CERT_local; - -static void -test_tortls_try_to_extract_certs_from_tls(void *ignored) -{ - (void)ignored; - tor_tls_t *tls; - X509 *cert = NULL, *id_cert = NULL, *c1 = NULL, *c2 = NULL; - SESS_CERT_local *sess = NULL; - - c1 = read_cert_from(validCertString); - c2 = read_cert_from(caCertString); - - tls = tor_malloc_zero(sizeof(tor_tls_t)); - tls->ssl = tor_malloc_zero(sizeof(SSL)); - tls->ssl->session = tor_malloc_zero(sizeof(SSL_SESSION)); - sess = tor_malloc_zero(sizeof(SESS_CERT_local)); - tls->ssl->session->sess_cert = (void *)sess; - - try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); - tt_assert(!cert); - tt_assert(!id_cert); - - tls->ssl->session->peer = c1; - try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); - tt_assert(cert == c1); - tt_assert(!id_cert); - X509_free(cert); /* decrease refcnt */ - - sess->cert_chain = sk_X509_new_null(); - try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); - tt_assert(cert == c1); - tt_assert(!id_cert); - X509_free(cert); /* decrease refcnt */ - - sk_X509_push(sess->cert_chain, c1); - sk_X509_push(sess->cert_chain, c2); - - try_to_extract_certs_from_tls(LOG_WARN, tls, &cert, &id_cert); - tt_assert(cert == c1); - tt_assert(id_cert); - X509_free(cert); /* decrease refcnt */ - X509_free(id_cert); /* decrease refcnt */ - - done: - sk_X509_free(sess->cert_chain); - tor_free(sess); - tor_free(tls->ssl->session); - tor_free(tls->ssl); - tor_free(tls); - X509_free(c1); - X509_free(c2); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE static void test_tortls_get_peer_cert(void *ignored) { @@ -1112,11 +733,6 @@ tor_tls_block_renegotiation(tls); -#ifndef OPENSSL_1_1_API - tt_assert(!(tls->ssl->s3->flags & - SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)); -#endif - done: tor_free(tls->ssl->s3); tor_free(tls->ssl); @@ -1199,93 +815,6 @@ #endif /* !defined(OPENSSL_OPAQUE) */ #ifndef OPENSSL_OPAQUE -static SSL_CIPHER *fixed_cipher1 = NULL; -static SSL_CIPHER *fixed_cipher2 = NULL; -static const SSL_CIPHER * -fake_get_cipher(unsigned ncipher) -{ - - switch (ncipher) { - case 1: - return fixed_cipher1; - case 2: - return fixed_cipher2; - default: - return NULL; - } -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE -static void -test_tortls_find_cipher_by_id(void *ignored) -{ - (void)ignored; - int ret; - SSL *ssl; - SSL_CTX *ctx; - const SSL_METHOD *m = TLSv1_method(); - SSL_METHOD *empty_method = tor_malloc_zero(sizeof(SSL_METHOD)); - - fixed_cipher1 = tor_malloc_zero(sizeof(SSL_CIPHER)); - fixed_cipher2 = tor_malloc_zero(sizeof(SSL_CIPHER)); - fixed_cipher2->id = 0xC00A; - - library_init(); - - ctx = SSL_CTX_new(m); - ssl = SSL_new(ctx); - - ret = find_cipher_by_id(ssl, NULL, 0xC00A); - tt_int_op(ret, OP_EQ, 1); - - ret = find_cipher_by_id(ssl, m, 0xC00A); - tt_int_op(ret, OP_EQ, 1); - - ret = find_cipher_by_id(ssl, m, 0xFFFF); - tt_int_op(ret, OP_EQ, 0); - - ret = find_cipher_by_id(ssl, empty_method, 0xC00A); - tt_int_op(ret, OP_EQ, 1); - - ret = find_cipher_by_id(ssl, empty_method, 0xFFFF); -#ifdef HAVE_SSL_CIPHER_FIND - tt_int_op(ret, OP_EQ, 0); -#else - tt_int_op(ret, OP_EQ, 1); -#endif - - empty_method->get_cipher = fake_get_cipher; - ret = find_cipher_by_id(ssl, empty_method, 0xC00A); - tt_int_op(ret, OP_EQ, 1); - - empty_method->get_cipher = m->get_cipher; - empty_method->num_ciphers = m->num_ciphers; - ret = find_cipher_by_id(ssl, empty_method, 0xC00A); - tt_int_op(ret, OP_EQ, 1); - - empty_method->get_cipher = fake_get_cipher; - empty_method->num_ciphers = m->num_ciphers; - ret = find_cipher_by_id(ssl, empty_method, 0xC00A); - tt_int_op(ret, OP_EQ, 1); - - empty_method->num_ciphers = fake_num_ciphers; - ret = find_cipher_by_id(ssl, empty_method, 0xC00A); -#ifdef HAVE_SSL_CIPHER_FIND - tt_int_op(ret, OP_EQ, 1); -#else - tt_int_op(ret, OP_EQ, 0); -#endif - - done: - tor_free(empty_method); - SSL_free(ssl); - SSL_CTX_free(ctx); - tor_free(fixed_cipher1); -} -#endif /* !defined(OPENSSL_OPAQUE) */ - -#ifndef OPENSSL_OPAQUE static void test_tortls_debug_state_callback(void *ignored) { @@ -2068,20 +1597,21 @@ (void)ignored; int ret; tor_x509_cert_t *cert = NULL, *scert = NULL; + time_t now = cert_strings_valid_at; scert = tor_malloc_zero(sizeof(tor_x509_cert_t)); - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, now, 0); tt_int_op(ret, OP_EQ, 0); cert = tor_malloc_zero(sizeof(tor_x509_cert_t)); - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, now, 0); tt_int_op(ret, OP_EQ, 0); tor_free(scert); tor_free(cert); cert = tor_x509_cert_new(read_cert_from(validCertString)); scert = tor_x509_cert_new(read_cert_from(caCertString)); - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, now, 0); tt_int_op(ret, OP_EQ, 1); #ifndef OPENSSL_OPAQUE @@ -2092,7 +1622,7 @@ ASN1_TIME_free(cert->cert->cert_info->validity->notAfter); cert->cert->cert_info->validity->notAfter = ASN1_TIME_set(NULL, time(NULL)-1000000); - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, now, 0); tt_int_op(ret, OP_EQ, 0); tor_x509_cert_free(cert); @@ -2101,7 +1631,7 @@ scert = tor_x509_cert_new(read_cert_from(caCertString)); X509_PUBKEY_free(cert->cert->cert_info->key); cert->cert->cert_info->key = NULL; - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 1); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, now, 1); tt_int_op(ret, OP_EQ, 0); #endif /* !defined(OPENSSL_OPAQUE) */ @@ -2112,7 +1642,7 @@ scert = tor_x509_cert_new(read_cert_from(caCertString)); /* This doesn't actually change the key in the cert. XXXXXX */ BN_one(EVP_PKEY_get1_RSA(X509_get_pubkey(cert->cert))->n); - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 1); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, now, 1); tt_int_op(ret, OP_EQ, 0); tor_x509_cert_free(cert); @@ -2121,7 +1651,7 @@ scert = tor_x509_cert_new(read_cert_from(caCertString)); /* This doesn't actually change the key in the cert. XXXXXX */ X509_get_pubkey(cert->cert)->type = EVP_PKEY_EC; - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 1); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, now, 1); tt_int_op(ret, OP_EQ, 0); tor_x509_cert_free(cert); @@ -2130,7 +1660,7 @@ scert = tor_x509_cert_new(read_cert_from(caCertString)); /* This doesn't actually change the key in the cert. XXXXXX */ X509_get_pubkey(cert->cert)->type = EVP_PKEY_EC; - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, now, 0); tt_int_op(ret, OP_EQ, 1); tor_x509_cert_free(cert); @@ -2140,7 +1670,7 @@ /* This doesn't actually change the key in the cert. XXXXXX */ X509_get_pubkey(cert->cert)->type = EVP_PKEY_EC; X509_get_pubkey(cert->cert)->ameth = NULL; - ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, time(NULL), 0); + ret = tor_tls_cert_is_valid(LOG_WARN, cert, scert, now, 0); tt_int_op(ret, OP_EQ, 0); #endif /* 0 */ @@ -2187,15 +1717,10 @@ LOCAL_TEST_CASE(always_accept_verify_cb, 0), INTRUSIVE_TEST_CASE(x509_cert_free, 0), INTRUSIVE_TEST_CASE(cert_get_key, 0), - LOCAL_TEST_CASE(get_my_client_auth_key, TT_FORK), INTRUSIVE_TEST_CASE(get_ciphersuite_name, 0), INTRUSIVE_TEST_CASE(classify_client_ciphers, 0), - LOCAL_TEST_CASE(client_is_using_v2_ciphers, 0), INTRUSIVE_TEST_CASE(get_pending_bytes, 0), - INTRUSIVE_TEST_CASE(SSL_SESSION_get_master_key, 0), - INTRUSIVE_TEST_CASE(get_tlssecrets, 0), INTRUSIVE_TEST_CASE(get_buffer_sizes, 0), - INTRUSIVE_TEST_CASE(try_to_extract_certs_from_tls, 0), INTRUSIVE_TEST_CASE(get_peer_cert, 0), INTRUSIVE_TEST_CASE(peer_has_cert, 0), INTRUSIVE_TEST_CASE(finish_handshake, 0), @@ -2209,7 +1734,6 @@ INTRUSIVE_TEST_CASE(unblock_renegotiation, 0), INTRUSIVE_TEST_CASE(set_renegotiate_callback, 0), LOCAL_TEST_CASE(set_logged_address, 0), - INTRUSIVE_TEST_CASE(find_cipher_by_id, 0), INTRUSIVE_TEST_CASE(session_secret_cb, 0), INTRUSIVE_TEST_CASE(debug_state_callback, 0), INTRUSIVE_TEST_CASE(context_new, TT_FORK /* redundant */), diff -Nru tor-0.4.8.16/src/test/test_util.c tor-0.4.9.6/src/test/test_util.c --- tor-0.4.8.16/src/test/test_util.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_util.c 2026-03-25 14:30:34.000000000 +0000 @@ -2876,8 +2876,8 @@ size_t szr, szr2; int r; - const size_t big = 1024*1024; - /* one megabyte of 0s. */ + const size_t big = 5*1024*1024; + /* five megabytes of 0s. */ input = tor_malloc_zero(big); /* Compress it into "result": it should fail. */ @@ -2934,8 +2934,8 @@ * In Tor we try not to generate them, and we don't accept them. */ (void) arg; - size_t one_million = 1<<20; - char *one_mb = tor_malloc_zero(one_million); + size_t six_megabytes = 6 * 1024 * 1024; + char *buffer = tor_malloc_zero(six_megabytes); char *result = NULL; size_t result_len = 0; tor_compress_state_t *state = NULL; @@ -2943,7 +2943,7 @@ /* Make sure we can't produce a compression bomb */ setup_full_capture_of_logs(LOG_WARN); tt_int_op(-1, OP_EQ, tor_compress(&result, &result_len, - one_mb, one_million, + buffer, six_megabytes, ZLIB_METHOD)); expect_log_msg_containing( "We compressed something and got an insanely high " @@ -2952,20 +2952,20 @@ teardown_capture_of_logs(); /* Here's a compression bomb that we made manually. */ - const char compression_bomb[1039] = - { 0x78, 0xDA, 0xED, 0xC1, 0x31, 0x01, 0x00, 0x00, 0x00, 0xC2, - 0xA0, 0xF5, 0x4F, 0x6D, 0x08, 0x5F, 0xA0 /* .... */ }; + #include "test/compression_bomb.h" + tt_int_op(-1, OP_EQ, tor_uncompress(&result, &result_len, - compression_bomb, 1039, - ZLIB_METHOD, 0, LOG_WARN)); + compression_bomb_gzip, + compression_bomb_gzip_len, + GZIP_METHOD, 0, LOG_WARN)); /* Now try streaming that. */ - state = tor_compress_new(0, ZLIB_METHOD, HIGH_COMPRESSION); + state = tor_compress_new(0, GZIP_METHOD, HIGH_COMPRESSION); tor_compress_output_t r; - const char *inp = compression_bomb; - size_t inlen = 1039; + const char *inp = compression_bomb_gzip; + size_t inlen = compression_bomb_gzip_len; do { - char *outp = one_mb; + char *outp = buffer; size_t outleft = 4096; /* small on purpose */ r = tor_compress_process(state, &outp, &outleft, &inp, &inlen, 0); tt_int_op(inlen, OP_NE, 0); @@ -2974,7 +2974,7 @@ tt_int_op(r, OP_EQ, TOR_COMPRESS_ERROR); done: - tor_free(one_mb); + tor_free(buffer); tor_compress_free(state); } @@ -4173,11 +4173,11 @@ "howdy world. how are you? i hope it's fine.\n" "hello kitty\n" "third line"; - char *line2 = strchr(long_string,'\n')+1; - char *line3 = strchr(line2,'\n')+1; + const char *line2 = strchr(long_string,'\n')+1; + const char *line3 = strchr(line2,'\n')+1; const char *short_string = "hello kitty\n" "second line\n"; - char *short_line2 = strchr(short_string,'\n')+1; + const char *short_line2 = strchr(short_string,'\n')+1; (void)ptr; diff -Nru tor-0.4.8.16/src/test/test_util_format.c tor-0.4.9.6/src/test/test_util_format.c --- tor-0.4.8.16/src/test/test_util_format.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/test/test_util_format.c 2026-03-25 14:30:34.000000000 +0000 @@ -13,7 +13,7 @@ test_util_format_unaligned_accessors(void *ignored) { (void)ignored; - char buf[9] = "onionsoup"; // 6f6e696f6e736f7570 + NONSTRING char buf[9] = "onionsoup"; // 6f6e696f6e736f7570 tt_u64_op(get_uint64(buf+1), OP_EQ, tor_htonll(UINT64_C(0x6e696f6e736f7570))); diff -Nru tor-0.4.8.16/src/tools/include.am tor-0.4.9.6/src/tools/include.am --- tor-0.4.8.16/src/tools/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/tools/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -9,7 +9,7 @@ src_tools_tor_resolve_LDADD = \ src/trunnel/libor-trunnel.a \ $(TOR_UTIL_LIBS) \ - $(TOR_CRYPTO_LIBS) $(TOR_LIBS_CRYPTLIB)\ + $(TOR_CRYPTO_LIBS) $(TOR_LIBS_CRYPTLIB)\ @TOR_LIB_MATH@ @TOR_LIB_WS32@ @TOR_LIB_IPHLPAPI@ @TOR_LIB_SHLWAPI@ @TOR_LIB_USERENV@ if COVERAGE_ENABLED @@ -41,8 +41,8 @@ src_tools_tor_print_ed_signing_cert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ src_tools_tor_print_ed_signing_cert_LDADD = \ src/trunnel/libor-trunnel.a \ - $(TOR_CRYPTO_LIBS) \ - $(TOR_UTIL_LIBS) \ + $(TOR_CRYPTO_LIBS) \ + $(TOR_UTIL_LIBS) \ @TOR_LIB_MATH@ $(TOR_LIBS_CRYPTLIB) \ @TOR_LIB_WS32@ @TOR_LIB_USERENV@ @TOR_LIB_SHLWAPI@ @TOR_LIB_GDI@ @@ -66,6 +66,6 @@ if BUILD_LIBTORRUNNER noinst_LIBRARIES += src/tools/libtorrunner.a src_tools_libtorrunner_a_SOURCES = \ - src/tools/tor_runner.c \ - src/feature/api/tor_api.c + src/tools/tor_runner.c \ + src/feature/api/tor_api.c endif diff -Nru tor-0.4.8.16/src/tools/tor-resolve.c tor-0.4.9.6/src/tools/tor-resolve.c --- tor-0.4.8.16/src/tools/tor-resolve.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/tools/tor-resolve.c 2026-03-25 14:30:34.000000000 +0000 @@ -385,7 +385,7 @@ tor_addr_make_unspec(result_addr); *result_hostname = NULL; - s = tor_open_socket(PF_INET,SOCK_STREAM,IPPROTO_TCP); + s = tor_open_socket(sockshost->family,SOCK_STREAM,IPPROTO_TCP); if (s<0) { log_sock_error("creating_socket", -1); return -1; diff -Nru tor-0.4.8.16/src/trunnel/include.am tor-0.4.9.6/src/trunnel/include.am --- tor-0.4.8.16/src/trunnel/include.am 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/trunnel/include.am 2026-03-25 14:30:34.000000000 +0000 @@ -17,45 +17,48 @@ src/trunnel/congestion_control.trunnel \ src/trunnel/socks5.trunnel \ src/trunnel/circpad_negotiation.trunnel \ - src/trunnel/conflux.trunnel + src/trunnel/conflux.trunnel \ + src/trunnel/subproto_request.trunnel TRUNNELSOURCES = \ src/ext/trunnel/trunnel.c \ src/trunnel/ed25519_cert.c \ src/trunnel/extension.c \ src/trunnel/link_handshake.c \ - src/trunnel/pwbox.c \ - src/trunnel/hs/cell_establish_intro.c \ + src/trunnel/pwbox.c \ + src/trunnel/hs/cell_establish_intro.c \ src/trunnel/hs/cell_introduce1.c \ src/trunnel/hs/cell_rendezvous.c \ src/trunnel/channelpadding_negotiation.c \ - src/trunnel/sendme_cell.c \ - src/trunnel/flow_control_cells.c \ - src/trunnel/congestion_control.c \ + src/trunnel/sendme_cell.c \ + src/trunnel/flow_control_cells.c \ + src/trunnel/congestion_control.c \ src/trunnel/socks5.c \ src/trunnel/netinfo.c \ src/trunnel/circpad_negotiation.c \ - src/trunnel/conflux.c + src/trunnel/conflux.c \ + src/trunnel/subproto_request.c TRUNNELHEADERS = \ - src/ext/trunnel/trunnel.h \ - src/ext/trunnel/trunnel-impl.h \ - src/trunnel/trunnel-local.h \ - src/trunnel/ed25519_cert.h \ + src/ext/trunnel/trunnel.h \ + src/ext/trunnel/trunnel-impl.h \ + src/trunnel/trunnel-local.h \ + src/trunnel/ed25519_cert.h \ src/trunnel/extension.h \ - src/trunnel/link_handshake.h \ - src/trunnel/pwbox.h \ - src/trunnel/hs/cell_establish_intro.h \ + src/trunnel/link_handshake.h \ + src/trunnel/pwbox.h \ + src/trunnel/hs/cell_establish_intro.h \ src/trunnel/hs/cell_introduce1.h \ src/trunnel/hs/cell_rendezvous.h \ src/trunnel/channelpadding_negotiation.h \ - src/trunnel/sendme_cell.h \ - src/trunnel/flow_control_cells.h \ - src/trunnel/congestion_control.h \ - src/trunnel/socks5.h \ + src/trunnel/sendme_cell.h \ + src/trunnel/flow_control_cells.h \ + src/trunnel/congestion_control.h \ + src/trunnel/socks5.h \ src/trunnel/netinfo.h \ src/trunnel/circpad_negotiation.h \ - src/trunnel/conflux.h + src/trunnel/conflux.h \ + src/trunnel/subproto_request.h src_trunnel_libor_trunnel_a_SOURCES = $(TRUNNELSOURCES) src_trunnel_libor_trunnel_a_CPPFLAGS = \ diff -Nru tor-0.4.8.16/src/trunnel/link_handshake.c tor-0.4.9.6/src/trunnel/link_handshake.c --- tor-0.4.8.16/src/trunnel/link_handshake.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/trunnel/link_handshake.c 2026-03-25 14:30:34.000000000 +0000 @@ -28,6 +28,738 @@ } \ } while (0) +auth1_t * +auth1_new(void) +{ + auth1_t *val = trunnel_calloc(1, sizeof(auth1_t)); + if (NULL == val) + return NULL; + return val; +} + +/** Release all storage held inside 'obj', but do not free 'obj'. + */ +static void +auth1_clear(auth1_t *obj) +{ + (void) obj; + TRUNNEL_DYNARRAY_WIPE(&obj->sig); + TRUNNEL_DYNARRAY_CLEAR(&obj->sig); +} + +void +auth1_free(auth1_t *obj) +{ + if (obj == NULL) + return; + auth1_clear(obj); + trunnel_memwipe(obj, sizeof(auth1_t)); + trunnel_free_(obj); +} + +size_t +auth1_getlen_type(const auth1_t *inp) +{ + (void)inp; return 8; +} + +uint8_t +auth1_get_type(auth1_t *inp, size_t idx) +{ + trunnel_assert(idx < 8); + return inp->type[idx]; +} + +uint8_t +auth1_getconst_type(const auth1_t *inp, size_t idx) +{ + return auth1_get_type((auth1_t*)inp, idx); +} +int +auth1_set_type(auth1_t *inp, size_t idx, uint8_t elt) +{ + trunnel_assert(idx < 8); + inp->type[idx] = elt; + return 0; +} + +uint8_t * +auth1_getarray_type(auth1_t *inp) +{ + return inp->type; +} +const uint8_t * +auth1_getconstarray_type(const auth1_t *inp) +{ + return (const uint8_t *)auth1_getarray_type((auth1_t*)inp); +} +size_t +auth1_getlen_cid(const auth1_t *inp) +{ + (void)inp; return 32; +} + +uint8_t +auth1_get_cid(auth1_t *inp, size_t idx) +{ + trunnel_assert(idx < 32); + return inp->cid[idx]; +} + +uint8_t +auth1_getconst_cid(const auth1_t *inp, size_t idx) +{ + return auth1_get_cid((auth1_t*)inp, idx); +} +int +auth1_set_cid(auth1_t *inp, size_t idx, uint8_t elt) +{ + trunnel_assert(idx < 32); + inp->cid[idx] = elt; + return 0; +} + +uint8_t * +auth1_getarray_cid(auth1_t *inp) +{ + return inp->cid; +} +const uint8_t * +auth1_getconstarray_cid(const auth1_t *inp) +{ + return (const uint8_t *)auth1_getarray_cid((auth1_t*)inp); +} +size_t +auth1_getlen_sid(const auth1_t *inp) +{ + (void)inp; return 32; +} + +uint8_t +auth1_get_sid(auth1_t *inp, size_t idx) +{ + trunnel_assert(idx < 32); + return inp->sid[idx]; +} + +uint8_t +auth1_getconst_sid(const auth1_t *inp, size_t idx) +{ + return auth1_get_sid((auth1_t*)inp, idx); +} +int +auth1_set_sid(auth1_t *inp, size_t idx, uint8_t elt) +{ + trunnel_assert(idx < 32); + inp->sid[idx] = elt; + return 0; +} + +uint8_t * +auth1_getarray_sid(auth1_t *inp) +{ + return inp->sid; +} +const uint8_t * +auth1_getconstarray_sid(const auth1_t *inp) +{ + return (const uint8_t *)auth1_getarray_sid((auth1_t*)inp); +} +size_t +auth1_getlen_cid_ed(const auth1_t *inp) +{ + (void)inp; return 32; +} + +uint8_t +auth1_get_cid_ed(auth1_t *inp, size_t idx) +{ + trunnel_assert(idx < 32); + return inp->cid_ed[idx]; +} + +uint8_t +auth1_getconst_cid_ed(const auth1_t *inp, size_t idx) +{ + return auth1_get_cid_ed((auth1_t*)inp, idx); +} +int +auth1_set_cid_ed(auth1_t *inp, size_t idx, uint8_t elt) +{ + trunnel_assert(idx < 32); + inp->cid_ed[idx] = elt; + return 0; +} + +uint8_t * +auth1_getarray_cid_ed(auth1_t *inp) +{ + return inp->cid_ed; +} +const uint8_t * +auth1_getconstarray_cid_ed(const auth1_t *inp) +{ + return (const uint8_t *)auth1_getarray_cid_ed((auth1_t*)inp); +} +size_t +auth1_getlen_sid_ed(const auth1_t *inp) +{ + (void)inp; return 32; +} + +uint8_t +auth1_get_sid_ed(auth1_t *inp, size_t idx) +{ + trunnel_assert(idx < 32); + return inp->sid_ed[idx]; +} + +uint8_t +auth1_getconst_sid_ed(const auth1_t *inp, size_t idx) +{ + return auth1_get_sid_ed((auth1_t*)inp, idx); +} +int +auth1_set_sid_ed(auth1_t *inp, size_t idx, uint8_t elt) +{ + trunnel_assert(idx < 32); + inp->sid_ed[idx] = elt; + return 0; +} + +uint8_t * +auth1_getarray_sid_ed(auth1_t *inp) +{ + return inp->sid_ed; +} +const uint8_t * +auth1_getconstarray_sid_ed(const auth1_t *inp) +{ + return (const uint8_t *)auth1_getarray_sid_ed((auth1_t*)inp); +} +size_t +auth1_getlen_slog(const auth1_t *inp) +{ + (void)inp; return 32; +} + +uint8_t +auth1_get_slog(auth1_t *inp, size_t idx) +{ + trunnel_assert(idx < 32); + return inp->slog[idx]; +} + +uint8_t +auth1_getconst_slog(const auth1_t *inp, size_t idx) +{ + return auth1_get_slog((auth1_t*)inp, idx); +} +int +auth1_set_slog(auth1_t *inp, size_t idx, uint8_t elt) +{ + trunnel_assert(idx < 32); + inp->slog[idx] = elt; + return 0; +} + +uint8_t * +auth1_getarray_slog(auth1_t *inp) +{ + return inp->slog; +} +const uint8_t * +auth1_getconstarray_slog(const auth1_t *inp) +{ + return (const uint8_t *)auth1_getarray_slog((auth1_t*)inp); +} +size_t +auth1_getlen_clog(const auth1_t *inp) +{ + (void)inp; return 32; +} + +uint8_t +auth1_get_clog(auth1_t *inp, size_t idx) +{ + trunnel_assert(idx < 32); + return inp->clog[idx]; +} + +uint8_t +auth1_getconst_clog(const auth1_t *inp, size_t idx) +{ + return auth1_get_clog((auth1_t*)inp, idx); +} +int +auth1_set_clog(auth1_t *inp, size_t idx, uint8_t elt) +{ + trunnel_assert(idx < 32); + inp->clog[idx] = elt; + return 0; +} + +uint8_t * +auth1_getarray_clog(auth1_t *inp) +{ + return inp->clog; +} +const uint8_t * +auth1_getconstarray_clog(const auth1_t *inp) +{ + return (const uint8_t *)auth1_getarray_clog((auth1_t*)inp); +} +size_t +auth1_getlen_scert(const auth1_t *inp) +{ + (void)inp; return 32; +} + +uint8_t +auth1_get_scert(auth1_t *inp, size_t idx) +{ + trunnel_assert(idx < 32); + return inp->scert[idx]; +} + +uint8_t +auth1_getconst_scert(const auth1_t *inp, size_t idx) +{ + return auth1_get_scert((auth1_t*)inp, idx); +} +int +auth1_set_scert(auth1_t *inp, size_t idx, uint8_t elt) +{ + trunnel_assert(idx < 32); + inp->scert[idx] = elt; + return 0; +} + +uint8_t * +auth1_getarray_scert(auth1_t *inp) +{ + return inp->scert; +} +const uint8_t * +auth1_getconstarray_scert(const auth1_t *inp) +{ + return (const uint8_t *)auth1_getarray_scert((auth1_t*)inp); +} +size_t +auth1_getlen_tlssecrets(const auth1_t *inp) +{ + (void)inp; return 32; +} + +uint8_t +auth1_get_tlssecrets(auth1_t *inp, size_t idx) +{ + trunnel_assert(idx < 32); + return inp->tlssecrets[idx]; +} + +uint8_t +auth1_getconst_tlssecrets(const auth1_t *inp, size_t idx) +{ + return auth1_get_tlssecrets((auth1_t*)inp, idx); +} +int +auth1_set_tlssecrets(auth1_t *inp, size_t idx, uint8_t elt) +{ + trunnel_assert(idx < 32); + inp->tlssecrets[idx] = elt; + return 0; +} + +uint8_t * +auth1_getarray_tlssecrets(auth1_t *inp) +{ + return inp->tlssecrets; +} +const uint8_t * +auth1_getconstarray_tlssecrets(const auth1_t *inp) +{ + return (const uint8_t *)auth1_getarray_tlssecrets((auth1_t*)inp); +} +const uint8_t * +auth1_get_end_of_fixed_part(const auth1_t *inp) +{ + return inp->end_of_fixed_part; +} +size_t +auth1_getlen_rand(const auth1_t *inp) +{ + (void)inp; return 24; +} + +uint8_t +auth1_get_rand(auth1_t *inp, size_t idx) +{ + trunnel_assert(idx < 24); + return inp->rand[idx]; +} + +uint8_t +auth1_getconst_rand(const auth1_t *inp, size_t idx) +{ + return auth1_get_rand((auth1_t*)inp, idx); +} +int +auth1_set_rand(auth1_t *inp, size_t idx, uint8_t elt) +{ + trunnel_assert(idx < 24); + inp->rand[idx] = elt; + return 0; +} + +uint8_t * +auth1_getarray_rand(auth1_t *inp) +{ + return inp->rand; +} +const uint8_t * +auth1_getconstarray_rand(const auth1_t *inp) +{ + return (const uint8_t *)auth1_getarray_rand((auth1_t*)inp); +} +const uint8_t * +auth1_get_end_of_signed(const auth1_t *inp) +{ + return inp->end_of_signed; +} +size_t +auth1_getlen_sig(const auth1_t *inp) +{ + return TRUNNEL_DYNARRAY_LEN(&inp->sig); +} + +uint8_t +auth1_get_sig(auth1_t *inp, size_t idx) +{ + return TRUNNEL_DYNARRAY_GET(&inp->sig, idx); +} + +uint8_t +auth1_getconst_sig(const auth1_t *inp, size_t idx) +{ + return auth1_get_sig((auth1_t*)inp, idx); +} +int +auth1_set_sig(auth1_t *inp, size_t idx, uint8_t elt) +{ + TRUNNEL_DYNARRAY_SET(&inp->sig, idx, elt); + return 0; +} +int +auth1_add_sig(auth1_t *inp, uint8_t elt) +{ + TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->sig, elt, {}); + return 0; + trunnel_alloc_failed: + TRUNNEL_SET_ERROR_CODE(inp); + return -1; +} + +uint8_t * +auth1_getarray_sig(auth1_t *inp) +{ + return inp->sig.elts_; +} +const uint8_t * +auth1_getconstarray_sig(const auth1_t *inp) +{ + return (const uint8_t *)auth1_getarray_sig((auth1_t*)inp); +} +int +auth1_setlen_sig(auth1_t *inp, size_t newlen) +{ + uint8_t *newptr; + newptr = trunnel_dynarray_setlen(&inp->sig.allocated_, + &inp->sig.n_, inp->sig.elts_, newlen, + sizeof(inp->sig.elts_[0]), (trunnel_free_fn_t) NULL, + &inp->trunnel_error_code_); + if (newlen != 0 && newptr == NULL) + goto trunnel_alloc_failed; + inp->sig.elts_ = newptr; + return 0; + trunnel_alloc_failed: + TRUNNEL_SET_ERROR_CODE(inp); + return -1; +} +const char * +auth1_check(const auth1_t *obj) +{ + if (obj == NULL) + return "Object was NULL"; + if (obj->trunnel_error_code_) + return "A set function failed on this object"; + return NULL; +} + +ssize_t +auth1_encoded_len(const auth1_t *obj) +{ + ssize_t result = 0; + + if (NULL != auth1_check(obj)) + return -1; + + + /* Length of u8 type[8] */ + result += 8; + + /* Length of u8 cid[32] */ + result += 32; + + /* Length of u8 sid[32] */ + result += 32; + + /* Length of u8 cid_ed[32] */ + result += 32; + + /* Length of u8 sid_ed[32] */ + result += 32; + + /* Length of u8 slog[32] */ + result += 32; + + /* Length of u8 clog[32] */ + result += 32; + + /* Length of u8 scert[32] */ + result += 32; + + /* Length of u8 tlssecrets[32] */ + result += 32; + + /* Length of u8 rand[24] */ + result += 24; + + /* Length of u8 sig[] */ + result += TRUNNEL_DYNARRAY_LEN(&obj->sig); + return result; +} +int +auth1_clear_errors(auth1_t *obj) +{ + int r = obj->trunnel_error_code_; + obj->trunnel_error_code_ = 0; + return r; +} +ssize_t +auth1_encode(uint8_t *output, const size_t avail, const auth1_t *obj) +{ + ssize_t result = 0; + size_t written = 0; + uint8_t *ptr = output; + const char *msg; +#ifdef TRUNNEL_CHECK_ENCODED_LEN + const ssize_t encoded_len = auth1_encoded_len(obj); +#endif + + if (NULL != (msg = auth1_check(obj))) + goto check_failed; + +#ifdef TRUNNEL_CHECK_ENCODED_LEN + trunnel_assert(encoded_len >= 0); +#endif + + /* Encode u8 type[8] */ + trunnel_assert(written <= avail); + if (avail - written < 8) + goto truncated; + memcpy(ptr, obj->type, 8); + written += 8; ptr += 8; + + /* Encode u8 cid[32] */ + trunnel_assert(written <= avail); + if (avail - written < 32) + goto truncated; + memcpy(ptr, obj->cid, 32); + written += 32; ptr += 32; + + /* Encode u8 sid[32] */ + trunnel_assert(written <= avail); + if (avail - written < 32) + goto truncated; + memcpy(ptr, obj->sid, 32); + written += 32; ptr += 32; + + /* Encode u8 cid_ed[32] */ + trunnel_assert(written <= avail); + if (avail - written < 32) + goto truncated; + memcpy(ptr, obj->cid_ed, 32); + written += 32; ptr += 32; + + /* Encode u8 sid_ed[32] */ + trunnel_assert(written <= avail); + if (avail - written < 32) + goto truncated; + memcpy(ptr, obj->sid_ed, 32); + written += 32; ptr += 32; + + /* Encode u8 slog[32] */ + trunnel_assert(written <= avail); + if (avail - written < 32) + goto truncated; + memcpy(ptr, obj->slog, 32); + written += 32; ptr += 32; + + /* Encode u8 clog[32] */ + trunnel_assert(written <= avail); + if (avail - written < 32) + goto truncated; + memcpy(ptr, obj->clog, 32); + written += 32; ptr += 32; + + /* Encode u8 scert[32] */ + trunnel_assert(written <= avail); + if (avail - written < 32) + goto truncated; + memcpy(ptr, obj->scert, 32); + written += 32; ptr += 32; + + /* Encode u8 tlssecrets[32] */ + trunnel_assert(written <= avail); + if (avail - written < 32) + goto truncated; + memcpy(ptr, obj->tlssecrets, 32); + written += 32; ptr += 32; + + /* Encode u8 rand[24] */ + trunnel_assert(written <= avail); + if (avail - written < 24) + goto truncated; + memcpy(ptr, obj->rand, 24); + written += 24; ptr += 24; + + /* Encode u8 sig[] */ + { + size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->sig); + trunnel_assert(written <= avail); + if (avail - written < elt_len) + goto truncated; + if (elt_len) + memcpy(ptr, obj->sig.elts_, elt_len); + written += elt_len; ptr += elt_len; + } + + + trunnel_assert(ptr == output + written); +#ifdef TRUNNEL_CHECK_ENCODED_LEN + { + trunnel_assert(encoded_len >= 0); + trunnel_assert((size_t)encoded_len == written); + } + +#endif + + return written; + + truncated: + result = -2; + goto fail; + check_failed: + (void)msg; + result = -1; + goto fail; + fail: + trunnel_assert(result < 0); + return result; +} + +/** As auth1_parse(), but do not allocate the output object. + */ +static ssize_t +auth1_parse_into(auth1_t *obj, const uint8_t *input, const size_t len_in) +{ + const uint8_t *ptr = input; + size_t remaining = len_in; + ssize_t result = 0; + (void)result; + + /* Parse u8 type[8] */ + CHECK_REMAINING(8, truncated); + memcpy(obj->type, ptr, 8); + remaining -= 8; ptr += 8; + + /* Parse u8 cid[32] */ + CHECK_REMAINING(32, truncated); + memcpy(obj->cid, ptr, 32); + remaining -= 32; ptr += 32; + + /* Parse u8 sid[32] */ + CHECK_REMAINING(32, truncated); + memcpy(obj->sid, ptr, 32); + remaining -= 32; ptr += 32; + + /* Parse u8 cid_ed[32] */ + CHECK_REMAINING(32, truncated); + memcpy(obj->cid_ed, ptr, 32); + remaining -= 32; ptr += 32; + + /* Parse u8 sid_ed[32] */ + CHECK_REMAINING(32, truncated); + memcpy(obj->sid_ed, ptr, 32); + remaining -= 32; ptr += 32; + + /* Parse u8 slog[32] */ + CHECK_REMAINING(32, truncated); + memcpy(obj->slog, ptr, 32); + remaining -= 32; ptr += 32; + + /* Parse u8 clog[32] */ + CHECK_REMAINING(32, truncated); + memcpy(obj->clog, ptr, 32); + remaining -= 32; ptr += 32; + + /* Parse u8 scert[32] */ + CHECK_REMAINING(32, truncated); + memcpy(obj->scert, ptr, 32); + remaining -= 32; ptr += 32; + + /* Parse u8 tlssecrets[32] */ + CHECK_REMAINING(32, truncated); + memcpy(obj->tlssecrets, ptr, 32); + remaining -= 32; ptr += 32; + obj->end_of_fixed_part = ptr; + + /* Parse u8 rand[24] */ + CHECK_REMAINING(24, truncated); + memcpy(obj->rand, ptr, 24); + remaining -= 24; ptr += 24; + obj->end_of_signed = ptr; + + /* Parse u8 sig[] */ + TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->sig, remaining, {}); + obj->sig.n_ = remaining; + if (remaining) + memcpy(obj->sig.elts_, ptr, remaining); + ptr += remaining; remaining -= remaining; + trunnel_assert(ptr + remaining == input + len_in); + return len_in - remaining; + + truncated: + return -2; + trunnel_alloc_failed: + return -1; +} + +ssize_t +auth1_parse(auth1_t **output, const uint8_t *input, const size_t len_in) +{ + ssize_t result; + *output = auth1_new(); + if (NULL == *output) + return -1; + result = auth1_parse_into(*output, input, len_in); + if (result < 0) { + auth1_free(*output); + *output = NULL; + } + return result; +} auth_challenge_cell_t * auth_challenge_cell_new(void) { @@ -334,44 +1066,6 @@ } return result; } -auth_ctx_t * -auth_ctx_new(void) -{ - auth_ctx_t *val = trunnel_calloc(1, sizeof(auth_ctx_t)); - if (NULL == val) - return NULL; - return val; -} - -/** Release all storage held inside 'obj', but do not free 'obj'. - */ -static void -auth_ctx_clear(auth_ctx_t *obj) -{ - (void) obj; -} - -void -auth_ctx_free(auth_ctx_t *obj) -{ - if (obj == NULL) - return; - auth_ctx_clear(obj); - trunnel_memwipe(obj, sizeof(auth_ctx_t)); - trunnel_free_(obj); -} - -uint8_t -auth_ctx_get_is_ed(const auth_ctx_t *inp) -{ - return inp->is_ed; -} -int -auth_ctx_set_is_ed(auth_ctx_t *inp, uint8_t val) -{ - inp->is_ed = val; - return 0; -} certs_cell_cert_t * certs_cell_cert_new(void) { @@ -977,798 +1671,6 @@ *output = NULL; } return result; -} -auth1_t * -auth1_new(void) -{ - auth1_t *val = trunnel_calloc(1, sizeof(auth1_t)); - if (NULL == val) - return NULL; - return val; -} - -/** Release all storage held inside 'obj', but do not free 'obj'. - */ -static void -auth1_clear(auth1_t *obj) -{ - (void) obj; - TRUNNEL_DYNARRAY_WIPE(&obj->sig); - TRUNNEL_DYNARRAY_CLEAR(&obj->sig); -} - -void -auth1_free(auth1_t *obj) -{ - if (obj == NULL) - return; - auth1_clear(obj); - trunnel_memwipe(obj, sizeof(auth1_t)); - trunnel_free_(obj); -} - -size_t -auth1_getlen_type(const auth1_t *inp) -{ - (void)inp; return 8; -} - -uint8_t -auth1_get_type(auth1_t *inp, size_t idx) -{ - trunnel_assert(idx < 8); - return inp->type[idx]; -} - -uint8_t -auth1_getconst_type(const auth1_t *inp, size_t idx) -{ - return auth1_get_type((auth1_t*)inp, idx); -} -int -auth1_set_type(auth1_t *inp, size_t idx, uint8_t elt) -{ - trunnel_assert(idx < 8); - inp->type[idx] = elt; - return 0; -} - -uint8_t * -auth1_getarray_type(auth1_t *inp) -{ - return inp->type; -} -const uint8_t * -auth1_getconstarray_type(const auth1_t *inp) -{ - return (const uint8_t *)auth1_getarray_type((auth1_t*)inp); -} -size_t -auth1_getlen_cid(const auth1_t *inp) -{ - (void)inp; return 32; -} - -uint8_t -auth1_get_cid(auth1_t *inp, size_t idx) -{ - trunnel_assert(idx < 32); - return inp->cid[idx]; -} - -uint8_t -auth1_getconst_cid(const auth1_t *inp, size_t idx) -{ - return auth1_get_cid((auth1_t*)inp, idx); -} -int -auth1_set_cid(auth1_t *inp, size_t idx, uint8_t elt) -{ - trunnel_assert(idx < 32); - inp->cid[idx] = elt; - return 0; -} - -uint8_t * -auth1_getarray_cid(auth1_t *inp) -{ - return inp->cid; -} -const uint8_t * -auth1_getconstarray_cid(const auth1_t *inp) -{ - return (const uint8_t *)auth1_getarray_cid((auth1_t*)inp); -} -size_t -auth1_getlen_sid(const auth1_t *inp) -{ - (void)inp; return 32; -} - -uint8_t -auth1_get_sid(auth1_t *inp, size_t idx) -{ - trunnel_assert(idx < 32); - return inp->sid[idx]; -} - -uint8_t -auth1_getconst_sid(const auth1_t *inp, size_t idx) -{ - return auth1_get_sid((auth1_t*)inp, idx); -} -int -auth1_set_sid(auth1_t *inp, size_t idx, uint8_t elt) -{ - trunnel_assert(idx < 32); - inp->sid[idx] = elt; - return 0; -} - -uint8_t * -auth1_getarray_sid(auth1_t *inp) -{ - return inp->sid; -} -const uint8_t * -auth1_getconstarray_sid(const auth1_t *inp) -{ - return (const uint8_t *)auth1_getarray_sid((auth1_t*)inp); -} -size_t -auth1_getlen_u1_cid_ed(const auth1_t *inp) -{ - (void)inp; return 32; -} - -uint8_t -auth1_get_u1_cid_ed(auth1_t *inp, size_t idx) -{ - trunnel_assert(idx < 32); - return inp->u1_cid_ed[idx]; -} - -uint8_t -auth1_getconst_u1_cid_ed(const auth1_t *inp, size_t idx) -{ - return auth1_get_u1_cid_ed((auth1_t*)inp, idx); -} -int -auth1_set_u1_cid_ed(auth1_t *inp, size_t idx, uint8_t elt) -{ - trunnel_assert(idx < 32); - inp->u1_cid_ed[idx] = elt; - return 0; -} - -uint8_t * -auth1_getarray_u1_cid_ed(auth1_t *inp) -{ - return inp->u1_cid_ed; -} -const uint8_t * -auth1_getconstarray_u1_cid_ed(const auth1_t *inp) -{ - return (const uint8_t *)auth1_getarray_u1_cid_ed((auth1_t*)inp); -} -size_t -auth1_getlen_u1_sid_ed(const auth1_t *inp) -{ - (void)inp; return 32; -} - -uint8_t -auth1_get_u1_sid_ed(auth1_t *inp, size_t idx) -{ - trunnel_assert(idx < 32); - return inp->u1_sid_ed[idx]; -} - -uint8_t -auth1_getconst_u1_sid_ed(const auth1_t *inp, size_t idx) -{ - return auth1_get_u1_sid_ed((auth1_t*)inp, idx); -} -int -auth1_set_u1_sid_ed(auth1_t *inp, size_t idx, uint8_t elt) -{ - trunnel_assert(idx < 32); - inp->u1_sid_ed[idx] = elt; - return 0; -} - -uint8_t * -auth1_getarray_u1_sid_ed(auth1_t *inp) -{ - return inp->u1_sid_ed; -} -const uint8_t * -auth1_getconstarray_u1_sid_ed(const auth1_t *inp) -{ - return (const uint8_t *)auth1_getarray_u1_sid_ed((auth1_t*)inp); -} -size_t -auth1_getlen_slog(const auth1_t *inp) -{ - (void)inp; return 32; -} - -uint8_t -auth1_get_slog(auth1_t *inp, size_t idx) -{ - trunnel_assert(idx < 32); - return inp->slog[idx]; -} - -uint8_t -auth1_getconst_slog(const auth1_t *inp, size_t idx) -{ - return auth1_get_slog((auth1_t*)inp, idx); -} -int -auth1_set_slog(auth1_t *inp, size_t idx, uint8_t elt) -{ - trunnel_assert(idx < 32); - inp->slog[idx] = elt; - return 0; -} - -uint8_t * -auth1_getarray_slog(auth1_t *inp) -{ - return inp->slog; -} -const uint8_t * -auth1_getconstarray_slog(const auth1_t *inp) -{ - return (const uint8_t *)auth1_getarray_slog((auth1_t*)inp); -} -size_t -auth1_getlen_clog(const auth1_t *inp) -{ - (void)inp; return 32; -} - -uint8_t -auth1_get_clog(auth1_t *inp, size_t idx) -{ - trunnel_assert(idx < 32); - return inp->clog[idx]; -} - -uint8_t -auth1_getconst_clog(const auth1_t *inp, size_t idx) -{ - return auth1_get_clog((auth1_t*)inp, idx); -} -int -auth1_set_clog(auth1_t *inp, size_t idx, uint8_t elt) -{ - trunnel_assert(idx < 32); - inp->clog[idx] = elt; - return 0; -} - -uint8_t * -auth1_getarray_clog(auth1_t *inp) -{ - return inp->clog; -} -const uint8_t * -auth1_getconstarray_clog(const auth1_t *inp) -{ - return (const uint8_t *)auth1_getarray_clog((auth1_t*)inp); -} -size_t -auth1_getlen_scert(const auth1_t *inp) -{ - (void)inp; return 32; -} - -uint8_t -auth1_get_scert(auth1_t *inp, size_t idx) -{ - trunnel_assert(idx < 32); - return inp->scert[idx]; -} - -uint8_t -auth1_getconst_scert(const auth1_t *inp, size_t idx) -{ - return auth1_get_scert((auth1_t*)inp, idx); -} -int -auth1_set_scert(auth1_t *inp, size_t idx, uint8_t elt) -{ - trunnel_assert(idx < 32); - inp->scert[idx] = elt; - return 0; -} - -uint8_t * -auth1_getarray_scert(auth1_t *inp) -{ - return inp->scert; -} -const uint8_t * -auth1_getconstarray_scert(const auth1_t *inp) -{ - return (const uint8_t *)auth1_getarray_scert((auth1_t*)inp); -} -size_t -auth1_getlen_tlssecrets(const auth1_t *inp) -{ - (void)inp; return 32; -} - -uint8_t -auth1_get_tlssecrets(auth1_t *inp, size_t idx) -{ - trunnel_assert(idx < 32); - return inp->tlssecrets[idx]; -} - -uint8_t -auth1_getconst_tlssecrets(const auth1_t *inp, size_t idx) -{ - return auth1_get_tlssecrets((auth1_t*)inp, idx); -} -int -auth1_set_tlssecrets(auth1_t *inp, size_t idx, uint8_t elt) -{ - trunnel_assert(idx < 32); - inp->tlssecrets[idx] = elt; - return 0; -} - -uint8_t * -auth1_getarray_tlssecrets(auth1_t *inp) -{ - return inp->tlssecrets; -} -const uint8_t * -auth1_getconstarray_tlssecrets(const auth1_t *inp) -{ - return (const uint8_t *)auth1_getarray_tlssecrets((auth1_t*)inp); -} -const uint8_t * -auth1_get_end_of_fixed_part(const auth1_t *inp) -{ - return inp->end_of_fixed_part; -} -size_t -auth1_getlen_rand(const auth1_t *inp) -{ - (void)inp; return 24; -} - -uint8_t -auth1_get_rand(auth1_t *inp, size_t idx) -{ - trunnel_assert(idx < 24); - return inp->rand[idx]; -} - -uint8_t -auth1_getconst_rand(const auth1_t *inp, size_t idx) -{ - return auth1_get_rand((auth1_t*)inp, idx); -} -int -auth1_set_rand(auth1_t *inp, size_t idx, uint8_t elt) -{ - trunnel_assert(idx < 24); - inp->rand[idx] = elt; - return 0; -} - -uint8_t * -auth1_getarray_rand(auth1_t *inp) -{ - return inp->rand; -} -const uint8_t * -auth1_getconstarray_rand(const auth1_t *inp) -{ - return (const uint8_t *)auth1_getarray_rand((auth1_t*)inp); -} -const uint8_t * -auth1_get_end_of_signed(const auth1_t *inp) -{ - return inp->end_of_signed; -} -size_t -auth1_getlen_sig(const auth1_t *inp) -{ - return TRUNNEL_DYNARRAY_LEN(&inp->sig); -} - -uint8_t -auth1_get_sig(auth1_t *inp, size_t idx) -{ - return TRUNNEL_DYNARRAY_GET(&inp->sig, idx); -} - -uint8_t -auth1_getconst_sig(const auth1_t *inp, size_t idx) -{ - return auth1_get_sig((auth1_t*)inp, idx); -} -int -auth1_set_sig(auth1_t *inp, size_t idx, uint8_t elt) -{ - TRUNNEL_DYNARRAY_SET(&inp->sig, idx, elt); - return 0; -} -int -auth1_add_sig(auth1_t *inp, uint8_t elt) -{ - TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->sig, elt, {}); - return 0; - trunnel_alloc_failed: - TRUNNEL_SET_ERROR_CODE(inp); - return -1; -} - -uint8_t * -auth1_getarray_sig(auth1_t *inp) -{ - return inp->sig.elts_; -} -const uint8_t * -auth1_getconstarray_sig(const auth1_t *inp) -{ - return (const uint8_t *)auth1_getarray_sig((auth1_t*)inp); -} -int -auth1_setlen_sig(auth1_t *inp, size_t newlen) -{ - uint8_t *newptr; - newptr = trunnel_dynarray_setlen(&inp->sig.allocated_, - &inp->sig.n_, inp->sig.elts_, newlen, - sizeof(inp->sig.elts_[0]), (trunnel_free_fn_t) NULL, - &inp->trunnel_error_code_); - if (newlen != 0 && newptr == NULL) - goto trunnel_alloc_failed; - inp->sig.elts_ = newptr; - return 0; - trunnel_alloc_failed: - TRUNNEL_SET_ERROR_CODE(inp); - return -1; -} -const char * -auth1_check(const auth1_t *obj, const auth_ctx_t *auth_ctx_ctx) -{ - if (obj == NULL) - return "Object was NULL"; - if (obj->trunnel_error_code_) - return "A set function failed on this object"; - if (auth_ctx_ctx == NULL) - return "Context was NULL"; - switch (auth_ctx_ctx->is_ed) { - - case 0: - break; - - case 1: - break; - - default: - return "Bad tag for union"; - break; - } - return NULL; -} - -ssize_t -auth1_encoded_len(const auth1_t *obj, const auth_ctx_t *auth_ctx_ctx) -{ - ssize_t result = 0; - - if (NULL != auth1_check(obj, auth_ctx_ctx)) - return -1; - - - /* Length of u8 type[8] */ - result += 8; - - /* Length of u8 cid[32] */ - result += 32; - - /* Length of u8 sid[32] */ - result += 32; - switch (auth_ctx_ctx->is_ed) { - - case 0: - break; - - case 1: - - /* Length of u8 u1_cid_ed[32] */ - result += 32; - - /* Length of u8 u1_sid_ed[32] */ - result += 32; - break; - - default: - trunnel_assert(0); - break; - } - - /* Length of u8 slog[32] */ - result += 32; - - /* Length of u8 clog[32] */ - result += 32; - - /* Length of u8 scert[32] */ - result += 32; - - /* Length of u8 tlssecrets[32] */ - result += 32; - - /* Length of u8 rand[24] */ - result += 24; - - /* Length of u8 sig[] */ - result += TRUNNEL_DYNARRAY_LEN(&obj->sig); - return result; -} -int -auth1_clear_errors(auth1_t *obj) -{ - int r = obj->trunnel_error_code_; - obj->trunnel_error_code_ = 0; - return r; -} -ssize_t -auth1_encode(uint8_t *output, const size_t avail, const auth1_t *obj, const auth_ctx_t *auth_ctx_ctx) -{ - ssize_t result = 0; - size_t written = 0; - uint8_t *ptr = output; - const char *msg; -#ifdef TRUNNEL_CHECK_ENCODED_LEN - const ssize_t encoded_len = auth1_encoded_len(obj, auth_ctx_ctx); -#endif - - if (NULL != (msg = auth1_check(obj, auth_ctx_ctx))) - goto check_failed; - -#ifdef TRUNNEL_CHECK_ENCODED_LEN - trunnel_assert(encoded_len >= 0); -#endif - - /* Encode u8 type[8] */ - trunnel_assert(written <= avail); - if (avail - written < 8) - goto truncated; - memcpy(ptr, obj->type, 8); - written += 8; ptr += 8; - - /* Encode u8 cid[32] */ - trunnel_assert(written <= avail); - if (avail - written < 32) - goto truncated; - memcpy(ptr, obj->cid, 32); - written += 32; ptr += 32; - - /* Encode u8 sid[32] */ - trunnel_assert(written <= avail); - if (avail - written < 32) - goto truncated; - memcpy(ptr, obj->sid, 32); - written += 32; ptr += 32; - - /* Encode union u1[auth_ctx.is_ed] */ - trunnel_assert(written <= avail); - switch (auth_ctx_ctx->is_ed) { - - case 0: - break; - - case 1: - - /* Encode u8 u1_cid_ed[32] */ - trunnel_assert(written <= avail); - if (avail - written < 32) - goto truncated; - memcpy(ptr, obj->u1_cid_ed, 32); - written += 32; ptr += 32; - - /* Encode u8 u1_sid_ed[32] */ - trunnel_assert(written <= avail); - if (avail - written < 32) - goto truncated; - memcpy(ptr, obj->u1_sid_ed, 32); - written += 32; ptr += 32; - break; - - default: - trunnel_assert(0); - break; - } - - /* Encode u8 slog[32] */ - trunnel_assert(written <= avail); - if (avail - written < 32) - goto truncated; - memcpy(ptr, obj->slog, 32); - written += 32; ptr += 32; - - /* Encode u8 clog[32] */ - trunnel_assert(written <= avail); - if (avail - written < 32) - goto truncated; - memcpy(ptr, obj->clog, 32); - written += 32; ptr += 32; - - /* Encode u8 scert[32] */ - trunnel_assert(written <= avail); - if (avail - written < 32) - goto truncated; - memcpy(ptr, obj->scert, 32); - written += 32; ptr += 32; - - /* Encode u8 tlssecrets[32] */ - trunnel_assert(written <= avail); - if (avail - written < 32) - goto truncated; - memcpy(ptr, obj->tlssecrets, 32); - written += 32; ptr += 32; - - /* Encode u8 rand[24] */ - trunnel_assert(written <= avail); - if (avail - written < 24) - goto truncated; - memcpy(ptr, obj->rand, 24); - written += 24; ptr += 24; - - /* Encode u8 sig[] */ - { - size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->sig); - trunnel_assert(written <= avail); - if (avail - written < elt_len) - goto truncated; - if (elt_len) - memcpy(ptr, obj->sig.elts_, elt_len); - written += elt_len; ptr += elt_len; - } - - - trunnel_assert(ptr == output + written); -#ifdef TRUNNEL_CHECK_ENCODED_LEN - { - trunnel_assert(encoded_len >= 0); - trunnel_assert((size_t)encoded_len == written); - } - -#endif - - return written; - - truncated: - result = -2; - goto fail; - check_failed: - (void)msg; - result = -1; - goto fail; - fail: - trunnel_assert(result < 0); - return result; -} - -/** As auth1_parse(), but do not allocate the output object. - */ -static ssize_t -auth1_parse_into(auth1_t *obj, const uint8_t *input, const size_t len_in, const auth_ctx_t *auth_ctx_ctx) -{ - const uint8_t *ptr = input; - size_t remaining = len_in; - ssize_t result = 0; - (void)result; - if (auth_ctx_ctx == NULL) - return -1; - - /* Parse u8 type[8] */ - CHECK_REMAINING(8, truncated); - memcpy(obj->type, ptr, 8); - remaining -= 8; ptr += 8; - - /* Parse u8 cid[32] */ - CHECK_REMAINING(32, truncated); - memcpy(obj->cid, ptr, 32); - remaining -= 32; ptr += 32; - - /* Parse u8 sid[32] */ - CHECK_REMAINING(32, truncated); - memcpy(obj->sid, ptr, 32); - remaining -= 32; ptr += 32; - - /* Parse union u1[auth_ctx.is_ed] */ - switch (auth_ctx_ctx->is_ed) { - - case 0: - break; - - case 1: - - /* Parse u8 u1_cid_ed[32] */ - CHECK_REMAINING(32, truncated); - memcpy(obj->u1_cid_ed, ptr, 32); - remaining -= 32; ptr += 32; - - /* Parse u8 u1_sid_ed[32] */ - CHECK_REMAINING(32, truncated); - memcpy(obj->u1_sid_ed, ptr, 32); - remaining -= 32; ptr += 32; - break; - - default: - goto fail; - break; - } - - /* Parse u8 slog[32] */ - CHECK_REMAINING(32, truncated); - memcpy(obj->slog, ptr, 32); - remaining -= 32; ptr += 32; - - /* Parse u8 clog[32] */ - CHECK_REMAINING(32, truncated); - memcpy(obj->clog, ptr, 32); - remaining -= 32; ptr += 32; - - /* Parse u8 scert[32] */ - CHECK_REMAINING(32, truncated); - memcpy(obj->scert, ptr, 32); - remaining -= 32; ptr += 32; - - /* Parse u8 tlssecrets[32] */ - CHECK_REMAINING(32, truncated); - memcpy(obj->tlssecrets, ptr, 32); - remaining -= 32; ptr += 32; - obj->end_of_fixed_part = ptr; - - /* Parse u8 rand[24] */ - CHECK_REMAINING(24, truncated); - memcpy(obj->rand, ptr, 24); - remaining -= 24; ptr += 24; - obj->end_of_signed = ptr; - - /* Parse u8 sig[] */ - TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->sig, remaining, {}); - obj->sig.n_ = remaining; - if (remaining) - memcpy(obj->sig.elts_, ptr, remaining); - ptr += remaining; remaining -= remaining; - trunnel_assert(ptr + remaining == input + len_in); - return len_in - remaining; - - truncated: - return -2; - trunnel_alloc_failed: - return -1; - fail: - result = -1; - return result; -} - -ssize_t -auth1_parse(auth1_t **output, const uint8_t *input, const size_t len_in, const auth_ctx_t *auth_ctx_ctx) -{ - ssize_t result; - *output = auth1_new(); - if (NULL == *output) - return -1; - result = auth1_parse_into(*output, input, len_in, auth_ctx_ctx); - if (result < 0) { - auth1_free(*output); - *output = NULL; - } - return result; } certs_cell_t * certs_cell_new(void) diff -Nru tor-0.4.8.16/src/trunnel/link_handshake.h tor-0.4.9.6/src/trunnel/link_handshake.h --- tor-0.4.8.16/src/trunnel/link_handshake.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/trunnel/link_handshake.h 2026-03-25 14:30:34.000000000 +0000 @@ -15,6 +15,25 @@ #define CERTTYPE_ED_SIGN_LINK 5 #define CERTTYPE_ED_SIGN_AUTH 6 #define CERTTYPE_RSA1024_ID_EDID 7 +#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_AUTH1) +struct auth1_st { + uint8_t type[8]; + uint8_t cid[32]; + uint8_t sid[32]; + uint8_t cid_ed[32]; + uint8_t sid_ed[32]; + uint8_t slog[32]; + uint8_t clog[32]; + uint8_t scert[32]; + uint8_t tlssecrets[32]; + const uint8_t *end_of_fixed_part; + uint8_t rand[24]; + const uint8_t *end_of_signed; + TRUNNEL_DYNARRAY_HEAD(, uint8_t) sig; + uint8_t trunnel_error_code_; +}; +#endif +typedef struct auth1_st auth1_t; #if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_AUTH_CHALLENGE_CELL) struct auth_challenge_cell_st { uint8_t challenge[32]; @@ -24,13 +43,6 @@ }; #endif typedef struct auth_challenge_cell_st auth_challenge_cell_t; -#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_AUTH_CTX) -struct auth_ctx_st { - uint8_t is_ed; - uint8_t trunnel_error_code_; -}; -#endif -typedef struct auth_ctx_st auth_ctx_t; #if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_CERTS_CELL_CERT) struct certs_cell_cert_st { uint8_t cert_type; @@ -51,25 +63,6 @@ }; #endif typedef struct rsa_ed_crosscert_st rsa_ed_crosscert_t; -#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_AUTH1) -struct auth1_st { - uint8_t type[8]; - uint8_t cid[32]; - uint8_t sid[32]; - uint8_t u1_cid_ed[32]; - uint8_t u1_sid_ed[32]; - uint8_t slog[32]; - uint8_t clog[32]; - uint8_t scert[32]; - uint8_t tlssecrets[32]; - const uint8_t *end_of_fixed_part; - uint8_t rand[24]; - const uint8_t *end_of_signed; - TRUNNEL_DYNARRAY_HEAD(, uint8_t) sig; - uint8_t trunnel_error_code_; -}; -#endif -typedef struct auth1_st auth1_t; #if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_CERTS_CELL) struct certs_cell_st { uint8_t n_certs; @@ -78,6 +71,292 @@ }; #endif typedef struct certs_cell_st certs_cell_t; +/** Return a newly allocated auth1 with all elements set to zero. + */ +auth1_t *auth1_new(void); +/** Release all storage held by the auth1 in 'victim'. (Do nothing if + * 'victim' is NULL.) + */ +void auth1_free(auth1_t *victim); +/** Try to parse a auth1 from the buffer in 'input', using up to + * 'len_in' bytes from the input buffer. On success, return the number + * of bytes consumed and set *output to the newly allocated auth1_t. + * On failure, return -2 if the input appears truncated, and -1 if the + * input is otherwise invalid. + */ +ssize_t auth1_parse(auth1_t **output, const uint8_t *input, const size_t len_in); +/** Return the number of bytes we expect to need to encode the auth1 + * in 'obj'. On failure, return a negative value. Note that this value + * may be an overestimate, and can even be an underestimate for + * certain unencodeable objects. + */ +ssize_t auth1_encoded_len(const auth1_t *obj); +/** Try to encode the auth1 from 'input' into the buffer at 'output', + * using up to 'avail' bytes of the output buffer. On success, return + * the number of bytes used. On failure, return -2 if the buffer was + * not long enough, and -1 if the input was invalid. + */ +ssize_t auth1_encode(uint8_t *output, size_t avail, const auth1_t *input); +/** Check whether the internal state of the auth1 in 'obj' is + * consistent. Return NULL if it is, and a short message if it is not. + */ +const char *auth1_check(const auth1_t *obj); +/** Clear any errors that were set on the object 'obj' by its setter + * functions. Return true iff errors were cleared. + */ +int auth1_clear_errors(auth1_t *obj); +/** Return the (constant) length of the array holding the type field + * of the auth1_t in 'inp'. + */ +size_t auth1_getlen_type(const auth1_t *inp); +/** Return the element at position 'idx' of the fixed array field type + * of the auth1_t in 'inp'. + */ +uint8_t auth1_get_type(auth1_t *inp, size_t idx); +/** As auth1_get_type, but take and return a const pointer + */ +uint8_t auth1_getconst_type(const auth1_t *inp, size_t idx); +/** Change the element at position 'idx' of the fixed array field type + * of the auth1_t in 'inp', so that it will hold the value 'elt'. + */ +int auth1_set_type(auth1_t *inp, size_t idx, uint8_t elt); +/** Return a pointer to the 8-element array field type of 'inp'. + */ +uint8_t * auth1_getarray_type(auth1_t *inp); +/** As auth1_get_type, but take and return a const pointer + */ +const uint8_t * auth1_getconstarray_type(const auth1_t *inp); +/** Return the (constant) length of the array holding the cid field of + * the auth1_t in 'inp'. + */ +size_t auth1_getlen_cid(const auth1_t *inp); +/** Return the element at position 'idx' of the fixed array field cid + * of the auth1_t in 'inp'. + */ +uint8_t auth1_get_cid(auth1_t *inp, size_t idx); +/** As auth1_get_cid, but take and return a const pointer + */ +uint8_t auth1_getconst_cid(const auth1_t *inp, size_t idx); +/** Change the element at position 'idx' of the fixed array field cid + * of the auth1_t in 'inp', so that it will hold the value 'elt'. + */ +int auth1_set_cid(auth1_t *inp, size_t idx, uint8_t elt); +/** Return a pointer to the 32-element array field cid of 'inp'. + */ +uint8_t * auth1_getarray_cid(auth1_t *inp); +/** As auth1_get_cid, but take and return a const pointer + */ +const uint8_t * auth1_getconstarray_cid(const auth1_t *inp); +/** Return the (constant) length of the array holding the sid field of + * the auth1_t in 'inp'. + */ +size_t auth1_getlen_sid(const auth1_t *inp); +/** Return the element at position 'idx' of the fixed array field sid + * of the auth1_t in 'inp'. + */ +uint8_t auth1_get_sid(auth1_t *inp, size_t idx); +/** As auth1_get_sid, but take and return a const pointer + */ +uint8_t auth1_getconst_sid(const auth1_t *inp, size_t idx); +/** Change the element at position 'idx' of the fixed array field sid + * of the auth1_t in 'inp', so that it will hold the value 'elt'. + */ +int auth1_set_sid(auth1_t *inp, size_t idx, uint8_t elt); +/** Return a pointer to the 32-element array field sid of 'inp'. + */ +uint8_t * auth1_getarray_sid(auth1_t *inp); +/** As auth1_get_sid, but take and return a const pointer + */ +const uint8_t * auth1_getconstarray_sid(const auth1_t *inp); +/** Return the (constant) length of the array holding the cid_ed field + * of the auth1_t in 'inp'. + */ +size_t auth1_getlen_cid_ed(const auth1_t *inp); +/** Return the element at position 'idx' of the fixed array field + * cid_ed of the auth1_t in 'inp'. + */ +uint8_t auth1_get_cid_ed(auth1_t *inp, size_t idx); +/** As auth1_get_cid_ed, but take and return a const pointer + */ +uint8_t auth1_getconst_cid_ed(const auth1_t *inp, size_t idx); +/** Change the element at position 'idx' of the fixed array field + * cid_ed of the auth1_t in 'inp', so that it will hold the value + * 'elt'. + */ +int auth1_set_cid_ed(auth1_t *inp, size_t idx, uint8_t elt); +/** Return a pointer to the 32-element array field cid_ed of 'inp'. + */ +uint8_t * auth1_getarray_cid_ed(auth1_t *inp); +/** As auth1_get_cid_ed, but take and return a const pointer + */ +const uint8_t * auth1_getconstarray_cid_ed(const auth1_t *inp); +/** Return the (constant) length of the array holding the sid_ed field + * of the auth1_t in 'inp'. + */ +size_t auth1_getlen_sid_ed(const auth1_t *inp); +/** Return the element at position 'idx' of the fixed array field + * sid_ed of the auth1_t in 'inp'. + */ +uint8_t auth1_get_sid_ed(auth1_t *inp, size_t idx); +/** As auth1_get_sid_ed, but take and return a const pointer + */ +uint8_t auth1_getconst_sid_ed(const auth1_t *inp, size_t idx); +/** Change the element at position 'idx' of the fixed array field + * sid_ed of the auth1_t in 'inp', so that it will hold the value + * 'elt'. + */ +int auth1_set_sid_ed(auth1_t *inp, size_t idx, uint8_t elt); +/** Return a pointer to the 32-element array field sid_ed of 'inp'. + */ +uint8_t * auth1_getarray_sid_ed(auth1_t *inp); +/** As auth1_get_sid_ed, but take and return a const pointer + */ +const uint8_t * auth1_getconstarray_sid_ed(const auth1_t *inp); +/** Return the (constant) length of the array holding the slog field + * of the auth1_t in 'inp'. + */ +size_t auth1_getlen_slog(const auth1_t *inp); +/** Return the element at position 'idx' of the fixed array field slog + * of the auth1_t in 'inp'. + */ +uint8_t auth1_get_slog(auth1_t *inp, size_t idx); +/** As auth1_get_slog, but take and return a const pointer + */ +uint8_t auth1_getconst_slog(const auth1_t *inp, size_t idx); +/** Change the element at position 'idx' of the fixed array field slog + * of the auth1_t in 'inp', so that it will hold the value 'elt'. + */ +int auth1_set_slog(auth1_t *inp, size_t idx, uint8_t elt); +/** Return a pointer to the 32-element array field slog of 'inp'. + */ +uint8_t * auth1_getarray_slog(auth1_t *inp); +/** As auth1_get_slog, but take and return a const pointer + */ +const uint8_t * auth1_getconstarray_slog(const auth1_t *inp); +/** Return the (constant) length of the array holding the clog field + * of the auth1_t in 'inp'. + */ +size_t auth1_getlen_clog(const auth1_t *inp); +/** Return the element at position 'idx' of the fixed array field clog + * of the auth1_t in 'inp'. + */ +uint8_t auth1_get_clog(auth1_t *inp, size_t idx); +/** As auth1_get_clog, but take and return a const pointer + */ +uint8_t auth1_getconst_clog(const auth1_t *inp, size_t idx); +/** Change the element at position 'idx' of the fixed array field clog + * of the auth1_t in 'inp', so that it will hold the value 'elt'. + */ +int auth1_set_clog(auth1_t *inp, size_t idx, uint8_t elt); +/** Return a pointer to the 32-element array field clog of 'inp'. + */ +uint8_t * auth1_getarray_clog(auth1_t *inp); +/** As auth1_get_clog, but take and return a const pointer + */ +const uint8_t * auth1_getconstarray_clog(const auth1_t *inp); +/** Return the (constant) length of the array holding the scert field + * of the auth1_t in 'inp'. + */ +size_t auth1_getlen_scert(const auth1_t *inp); +/** Return the element at position 'idx' of the fixed array field + * scert of the auth1_t in 'inp'. + */ +uint8_t auth1_get_scert(auth1_t *inp, size_t idx); +/** As auth1_get_scert, but take and return a const pointer + */ +uint8_t auth1_getconst_scert(const auth1_t *inp, size_t idx); +/** Change the element at position 'idx' of the fixed array field + * scert of the auth1_t in 'inp', so that it will hold the value + * 'elt'. + */ +int auth1_set_scert(auth1_t *inp, size_t idx, uint8_t elt); +/** Return a pointer to the 32-element array field scert of 'inp'. + */ +uint8_t * auth1_getarray_scert(auth1_t *inp); +/** As auth1_get_scert, but take and return a const pointer + */ +const uint8_t * auth1_getconstarray_scert(const auth1_t *inp); +/** Return the (constant) length of the array holding the tlssecrets + * field of the auth1_t in 'inp'. + */ +size_t auth1_getlen_tlssecrets(const auth1_t *inp); +/** Return the element at position 'idx' of the fixed array field + * tlssecrets of the auth1_t in 'inp'. + */ +uint8_t auth1_get_tlssecrets(auth1_t *inp, size_t idx); +/** As auth1_get_tlssecrets, but take and return a const pointer + */ +uint8_t auth1_getconst_tlssecrets(const auth1_t *inp, size_t idx); +/** Change the element at position 'idx' of the fixed array field + * tlssecrets of the auth1_t in 'inp', so that it will hold the value + * 'elt'. + */ +int auth1_set_tlssecrets(auth1_t *inp, size_t idx, uint8_t elt); +/** Return a pointer to the 32-element array field tlssecrets of + * 'inp'. + */ +uint8_t * auth1_getarray_tlssecrets(auth1_t *inp); +/** As auth1_get_tlssecrets, but take and return a const pointer + */ +const uint8_t * auth1_getconstarray_tlssecrets(const auth1_t *inp); +/** Return the position for end_of_fixed_part when we parsed this + * object + */ +const uint8_t * auth1_get_end_of_fixed_part(const auth1_t *inp); +/** Return the (constant) length of the array holding the rand field + * of the auth1_t in 'inp'. + */ +size_t auth1_getlen_rand(const auth1_t *inp); +/** Return the element at position 'idx' of the fixed array field rand + * of the auth1_t in 'inp'. + */ +uint8_t auth1_get_rand(auth1_t *inp, size_t idx); +/** As auth1_get_rand, but take and return a const pointer + */ +uint8_t auth1_getconst_rand(const auth1_t *inp, size_t idx); +/** Change the element at position 'idx' of the fixed array field rand + * of the auth1_t in 'inp', so that it will hold the value 'elt'. + */ +int auth1_set_rand(auth1_t *inp, size_t idx, uint8_t elt); +/** Return a pointer to the 24-element array field rand of 'inp'. + */ +uint8_t * auth1_getarray_rand(auth1_t *inp); +/** As auth1_get_rand, but take and return a const pointer + */ +const uint8_t * auth1_getconstarray_rand(const auth1_t *inp); +/** Return the position for end_of_signed when we parsed this object + */ +const uint8_t * auth1_get_end_of_signed(const auth1_t *inp); +/** Return the length of the dynamic array holding the sig field of + * the auth1_t in 'inp'. + */ +size_t auth1_getlen_sig(const auth1_t *inp); +/** Return the element at position 'idx' of the dynamic array field + * sig of the auth1_t in 'inp'. + */ +uint8_t auth1_get_sig(auth1_t *inp, size_t idx); +/** As auth1_get_sig, but take and return a const pointer + */ +uint8_t auth1_getconst_sig(const auth1_t *inp, size_t idx); +/** Change the element at position 'idx' of the dynamic array field + * sig of the auth1_t in 'inp', so that it will hold the value 'elt'. + */ +int auth1_set_sig(auth1_t *inp, size_t idx, uint8_t elt); +/** Append a new element 'elt' to the dynamic array field sig of the + * auth1_t in 'inp'. + */ +int auth1_add_sig(auth1_t *inp, uint8_t elt); +/** Return a pointer to the variable-length array field sig of 'inp'. + */ +uint8_t * auth1_getarray_sig(auth1_t *inp); +/** As auth1_get_sig, but take and return a const pointer + */ +const uint8_t * auth1_getconstarray_sig(const auth1_t *inp); +/** Change the length of the variable-length array field sig of 'inp' + * to 'newlen'.Fill extra elements with 0. Return 0 on success; return + * -1 and set the error code on 'inp' on failure. + */ +int auth1_setlen_sig(auth1_t *inp, size_t newlen); /** Return a newly allocated auth_challenge_cell with all elements set * to zero. */ @@ -181,21 +460,6 @@ * return -1 and set the error code on 'inp' on failure. */ int auth_challenge_cell_setlen_methods(auth_challenge_cell_t *inp, size_t newlen); -/** Return a newly allocated auth_ctx with all elements set to zero. - */ -auth_ctx_t *auth_ctx_new(void); -/** Release all storage held by the auth_ctx in 'victim'. (Do nothing - * if 'victim' is NULL.) - */ -void auth_ctx_free(auth_ctx_t *victim); -/** Return the value of the is_ed field of the auth_ctx_t in 'inp' - */ -uint8_t auth_ctx_get_is_ed(const auth_ctx_t *inp); -/** Set the value of the is_ed field of the auth_ctx_t in 'inp' to - * 'val'. Return 0 on success; return -1 and set the error code on - * 'inp' on failure. - */ -int auth_ctx_set_is_ed(auth_ctx_t *inp, uint8_t val); /** Return a newly allocated certs_cell_cert with all elements set to * zero. */ @@ -393,292 +657,6 @@ * -1 and set the error code on 'inp' on failure. */ int rsa_ed_crosscert_setlen_sig(rsa_ed_crosscert_t *inp, size_t newlen); -/** Return a newly allocated auth1 with all elements set to zero. - */ -auth1_t *auth1_new(void); -/** Release all storage held by the auth1 in 'victim'. (Do nothing if - * 'victim' is NULL.) - */ -void auth1_free(auth1_t *victim); -/** Try to parse a auth1 from the buffer in 'input', using up to - * 'len_in' bytes from the input buffer. On success, return the number - * of bytes consumed and set *output to the newly allocated auth1_t. - * On failure, return -2 if the input appears truncated, and -1 if the - * input is otherwise invalid. - */ -ssize_t auth1_parse(auth1_t **output, const uint8_t *input, const size_t len_in, const auth_ctx_t *auth_ctx_ctx); -/** Return the number of bytes we expect to need to encode the auth1 - * in 'obj'. On failure, return a negative value. Note that this value - * may be an overestimate, and can even be an underestimate for - * certain unencodeable objects. - */ -ssize_t auth1_encoded_len(const auth1_t *obj, const auth_ctx_t *auth_ctx_ctx); -/** Try to encode the auth1 from 'input' into the buffer at 'output', - * using up to 'avail' bytes of the output buffer. On success, return - * the number of bytes used. On failure, return -2 if the buffer was - * not long enough, and -1 if the input was invalid. - */ -ssize_t auth1_encode(uint8_t *output, size_t avail, const auth1_t *input, const auth_ctx_t *auth_ctx_ctx); -/** Check whether the internal state of the auth1 in 'obj' is - * consistent. Return NULL if it is, and a short message if it is not. - */ -const char *auth1_check(const auth1_t *obj, const auth_ctx_t *auth_ctx_ctx); -/** Clear any errors that were set on the object 'obj' by its setter - * functions. Return true iff errors were cleared. - */ -int auth1_clear_errors(auth1_t *obj); -/** Return the (constant) length of the array holding the type field - * of the auth1_t in 'inp'. - */ -size_t auth1_getlen_type(const auth1_t *inp); -/** Return the element at position 'idx' of the fixed array field type - * of the auth1_t in 'inp'. - */ -uint8_t auth1_get_type(auth1_t *inp, size_t idx); -/** As auth1_get_type, but take and return a const pointer - */ -uint8_t auth1_getconst_type(const auth1_t *inp, size_t idx); -/** Change the element at position 'idx' of the fixed array field type - * of the auth1_t in 'inp', so that it will hold the value 'elt'. - */ -int auth1_set_type(auth1_t *inp, size_t idx, uint8_t elt); -/** Return a pointer to the 8-element array field type of 'inp'. - */ -uint8_t * auth1_getarray_type(auth1_t *inp); -/** As auth1_get_type, but take and return a const pointer - */ -const uint8_t * auth1_getconstarray_type(const auth1_t *inp); -/** Return the (constant) length of the array holding the cid field of - * the auth1_t in 'inp'. - */ -size_t auth1_getlen_cid(const auth1_t *inp); -/** Return the element at position 'idx' of the fixed array field cid - * of the auth1_t in 'inp'. - */ -uint8_t auth1_get_cid(auth1_t *inp, size_t idx); -/** As auth1_get_cid, but take and return a const pointer - */ -uint8_t auth1_getconst_cid(const auth1_t *inp, size_t idx); -/** Change the element at position 'idx' of the fixed array field cid - * of the auth1_t in 'inp', so that it will hold the value 'elt'. - */ -int auth1_set_cid(auth1_t *inp, size_t idx, uint8_t elt); -/** Return a pointer to the 32-element array field cid of 'inp'. - */ -uint8_t * auth1_getarray_cid(auth1_t *inp); -/** As auth1_get_cid, but take and return a const pointer - */ -const uint8_t * auth1_getconstarray_cid(const auth1_t *inp); -/** Return the (constant) length of the array holding the sid field of - * the auth1_t in 'inp'. - */ -size_t auth1_getlen_sid(const auth1_t *inp); -/** Return the element at position 'idx' of the fixed array field sid - * of the auth1_t in 'inp'. - */ -uint8_t auth1_get_sid(auth1_t *inp, size_t idx); -/** As auth1_get_sid, but take and return a const pointer - */ -uint8_t auth1_getconst_sid(const auth1_t *inp, size_t idx); -/** Change the element at position 'idx' of the fixed array field sid - * of the auth1_t in 'inp', so that it will hold the value 'elt'. - */ -int auth1_set_sid(auth1_t *inp, size_t idx, uint8_t elt); -/** Return a pointer to the 32-element array field sid of 'inp'. - */ -uint8_t * auth1_getarray_sid(auth1_t *inp); -/** As auth1_get_sid, but take and return a const pointer - */ -const uint8_t * auth1_getconstarray_sid(const auth1_t *inp); -/** Return the (constant) length of the array holding the u1_cid_ed - * field of the auth1_t in 'inp'. - */ -size_t auth1_getlen_u1_cid_ed(const auth1_t *inp); -/** Return the element at position 'idx' of the fixed array field - * u1_cid_ed of the auth1_t in 'inp'. - */ -uint8_t auth1_get_u1_cid_ed(auth1_t *inp, size_t idx); -/** As auth1_get_u1_cid_ed, but take and return a const pointer - */ -uint8_t auth1_getconst_u1_cid_ed(const auth1_t *inp, size_t idx); -/** Change the element at position 'idx' of the fixed array field - * u1_cid_ed of the auth1_t in 'inp', so that it will hold the value - * 'elt'. - */ -int auth1_set_u1_cid_ed(auth1_t *inp, size_t idx, uint8_t elt); -/** Return a pointer to the 32-element array field u1_cid_ed of 'inp'. - */ -uint8_t * auth1_getarray_u1_cid_ed(auth1_t *inp); -/** As auth1_get_u1_cid_ed, but take and return a const pointer - */ -const uint8_t * auth1_getconstarray_u1_cid_ed(const auth1_t *inp); -/** Return the (constant) length of the array holding the u1_sid_ed - * field of the auth1_t in 'inp'. - */ -size_t auth1_getlen_u1_sid_ed(const auth1_t *inp); -/** Return the element at position 'idx' of the fixed array field - * u1_sid_ed of the auth1_t in 'inp'. - */ -uint8_t auth1_get_u1_sid_ed(auth1_t *inp, size_t idx); -/** As auth1_get_u1_sid_ed, but take and return a const pointer - */ -uint8_t auth1_getconst_u1_sid_ed(const auth1_t *inp, size_t idx); -/** Change the element at position 'idx' of the fixed array field - * u1_sid_ed of the auth1_t in 'inp', so that it will hold the value - * 'elt'. - */ -int auth1_set_u1_sid_ed(auth1_t *inp, size_t idx, uint8_t elt); -/** Return a pointer to the 32-element array field u1_sid_ed of 'inp'. - */ -uint8_t * auth1_getarray_u1_sid_ed(auth1_t *inp); -/** As auth1_get_u1_sid_ed, but take and return a const pointer - */ -const uint8_t * auth1_getconstarray_u1_sid_ed(const auth1_t *inp); -/** Return the (constant) length of the array holding the slog field - * of the auth1_t in 'inp'. - */ -size_t auth1_getlen_slog(const auth1_t *inp); -/** Return the element at position 'idx' of the fixed array field slog - * of the auth1_t in 'inp'. - */ -uint8_t auth1_get_slog(auth1_t *inp, size_t idx); -/** As auth1_get_slog, but take and return a const pointer - */ -uint8_t auth1_getconst_slog(const auth1_t *inp, size_t idx); -/** Change the element at position 'idx' of the fixed array field slog - * of the auth1_t in 'inp', so that it will hold the value 'elt'. - */ -int auth1_set_slog(auth1_t *inp, size_t idx, uint8_t elt); -/** Return a pointer to the 32-element array field slog of 'inp'. - */ -uint8_t * auth1_getarray_slog(auth1_t *inp); -/** As auth1_get_slog, but take and return a const pointer - */ -const uint8_t * auth1_getconstarray_slog(const auth1_t *inp); -/** Return the (constant) length of the array holding the clog field - * of the auth1_t in 'inp'. - */ -size_t auth1_getlen_clog(const auth1_t *inp); -/** Return the element at position 'idx' of the fixed array field clog - * of the auth1_t in 'inp'. - */ -uint8_t auth1_get_clog(auth1_t *inp, size_t idx); -/** As auth1_get_clog, but take and return a const pointer - */ -uint8_t auth1_getconst_clog(const auth1_t *inp, size_t idx); -/** Change the element at position 'idx' of the fixed array field clog - * of the auth1_t in 'inp', so that it will hold the value 'elt'. - */ -int auth1_set_clog(auth1_t *inp, size_t idx, uint8_t elt); -/** Return a pointer to the 32-element array field clog of 'inp'. - */ -uint8_t * auth1_getarray_clog(auth1_t *inp); -/** As auth1_get_clog, but take and return a const pointer - */ -const uint8_t * auth1_getconstarray_clog(const auth1_t *inp); -/** Return the (constant) length of the array holding the scert field - * of the auth1_t in 'inp'. - */ -size_t auth1_getlen_scert(const auth1_t *inp); -/** Return the element at position 'idx' of the fixed array field - * scert of the auth1_t in 'inp'. - */ -uint8_t auth1_get_scert(auth1_t *inp, size_t idx); -/** As auth1_get_scert, but take and return a const pointer - */ -uint8_t auth1_getconst_scert(const auth1_t *inp, size_t idx); -/** Change the element at position 'idx' of the fixed array field - * scert of the auth1_t in 'inp', so that it will hold the value - * 'elt'. - */ -int auth1_set_scert(auth1_t *inp, size_t idx, uint8_t elt); -/** Return a pointer to the 32-element array field scert of 'inp'. - */ -uint8_t * auth1_getarray_scert(auth1_t *inp); -/** As auth1_get_scert, but take and return a const pointer - */ -const uint8_t * auth1_getconstarray_scert(const auth1_t *inp); -/** Return the (constant) length of the array holding the tlssecrets - * field of the auth1_t in 'inp'. - */ -size_t auth1_getlen_tlssecrets(const auth1_t *inp); -/** Return the element at position 'idx' of the fixed array field - * tlssecrets of the auth1_t in 'inp'. - */ -uint8_t auth1_get_tlssecrets(auth1_t *inp, size_t idx); -/** As auth1_get_tlssecrets, but take and return a const pointer - */ -uint8_t auth1_getconst_tlssecrets(const auth1_t *inp, size_t idx); -/** Change the element at position 'idx' of the fixed array field - * tlssecrets of the auth1_t in 'inp', so that it will hold the value - * 'elt'. - */ -int auth1_set_tlssecrets(auth1_t *inp, size_t idx, uint8_t elt); -/** Return a pointer to the 32-element array field tlssecrets of - * 'inp'. - */ -uint8_t * auth1_getarray_tlssecrets(auth1_t *inp); -/** As auth1_get_tlssecrets, but take and return a const pointer - */ -const uint8_t * auth1_getconstarray_tlssecrets(const auth1_t *inp); -/** Return the position for end_of_fixed_part when we parsed this - * object - */ -const uint8_t * auth1_get_end_of_fixed_part(const auth1_t *inp); -/** Return the (constant) length of the array holding the rand field - * of the auth1_t in 'inp'. - */ -size_t auth1_getlen_rand(const auth1_t *inp); -/** Return the element at position 'idx' of the fixed array field rand - * of the auth1_t in 'inp'. - */ -uint8_t auth1_get_rand(auth1_t *inp, size_t idx); -/** As auth1_get_rand, but take and return a const pointer - */ -uint8_t auth1_getconst_rand(const auth1_t *inp, size_t idx); -/** Change the element at position 'idx' of the fixed array field rand - * of the auth1_t in 'inp', so that it will hold the value 'elt'. - */ -int auth1_set_rand(auth1_t *inp, size_t idx, uint8_t elt); -/** Return a pointer to the 24-element array field rand of 'inp'. - */ -uint8_t * auth1_getarray_rand(auth1_t *inp); -/** As auth1_get_rand, but take and return a const pointer - */ -const uint8_t * auth1_getconstarray_rand(const auth1_t *inp); -/** Return the position for end_of_signed when we parsed this object - */ -const uint8_t * auth1_get_end_of_signed(const auth1_t *inp); -/** Return the length of the dynamic array holding the sig field of - * the auth1_t in 'inp'. - */ -size_t auth1_getlen_sig(const auth1_t *inp); -/** Return the element at position 'idx' of the dynamic array field - * sig of the auth1_t in 'inp'. - */ -uint8_t auth1_get_sig(auth1_t *inp, size_t idx); -/** As auth1_get_sig, but take and return a const pointer - */ -uint8_t auth1_getconst_sig(const auth1_t *inp, size_t idx); -/** Change the element at position 'idx' of the dynamic array field - * sig of the auth1_t in 'inp', so that it will hold the value 'elt'. - */ -int auth1_set_sig(auth1_t *inp, size_t idx, uint8_t elt); -/** Append a new element 'elt' to the dynamic array field sig of the - * auth1_t in 'inp'. - */ -int auth1_add_sig(auth1_t *inp, uint8_t elt); -/** Return a pointer to the variable-length array field sig of 'inp'. - */ -uint8_t * auth1_getarray_sig(auth1_t *inp); -/** As auth1_get_sig, but take and return a const pointer - */ -const uint8_t * auth1_getconstarray_sig(const auth1_t *inp); -/** Change the length of the variable-length array field sig of 'inp' - * to 'newlen'.Fill extra elements with 0. Return 0 on success; return - * -1 and set the error code on 'inp' on failure. - */ -int auth1_setlen_sig(auth1_t *inp, size_t newlen); /** Return a newly allocated certs_cell with all elements set to zero. */ certs_cell_t *certs_cell_new(void); diff -Nru tor-0.4.8.16/src/trunnel/sendme_cell.c tor-0.4.9.6/src/trunnel/sendme_cell.c --- tor-0.4.8.16/src/trunnel/sendme_cell.c 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/trunnel/sendme_cell.c 2026-03-25 14:30:34.000000000 +0000 @@ -34,6 +34,7 @@ sendme_cell_t *val = trunnel_calloc(1, sizeof(sendme_cell_t)); if (NULL == val) return NULL; + val->data_len = 16; return val; } @@ -43,6 +44,8 @@ sendme_cell_clear(sendme_cell_t *obj) { (void) obj; + TRUNNEL_DYNARRAY_WIPE(&obj->data_v1_digest); + TRUNNEL_DYNARRAY_CLEAR(&obj->data_v1_digest); } void @@ -78,20 +81,23 @@ int sendme_cell_set_data_len(sendme_cell_t *inp, uint16_t val) { + if (! ((val == 16 || val == 20))) { + TRUNNEL_SET_ERROR_CODE(inp); + return -1; + } inp->data_len = val; return 0; } size_t sendme_cell_getlen_data_v1_digest(const sendme_cell_t *inp) { - (void)inp; return TRUNNEL_SENDME_V1_DIGEST_LEN; + return TRUNNEL_DYNARRAY_LEN(&inp->data_v1_digest); } uint8_t sendme_cell_get_data_v1_digest(sendme_cell_t *inp, size_t idx) { - trunnel_assert(idx < TRUNNEL_SENDME_V1_DIGEST_LEN); - return inp->data_v1_digest[idx]; + return TRUNNEL_DYNARRAY_GET(&inp->data_v1_digest, idx); } uint8_t @@ -102,21 +108,45 @@ int sendme_cell_set_data_v1_digest(sendme_cell_t *inp, size_t idx, uint8_t elt) { - trunnel_assert(idx < TRUNNEL_SENDME_V1_DIGEST_LEN); - inp->data_v1_digest[idx] = elt; + TRUNNEL_DYNARRAY_SET(&inp->data_v1_digest, idx, elt); + return 0; +} +int +sendme_cell_add_data_v1_digest(sendme_cell_t *inp, uint8_t elt) +{ + TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->data_v1_digest, elt, {}); return 0; + trunnel_alloc_failed: + TRUNNEL_SET_ERROR_CODE(inp); + return -1; } uint8_t * sendme_cell_getarray_data_v1_digest(sendme_cell_t *inp) { - return inp->data_v1_digest; + return inp->data_v1_digest.elts_; } const uint8_t * sendme_cell_getconstarray_data_v1_digest(const sendme_cell_t *inp) { return (const uint8_t *)sendme_cell_getarray_data_v1_digest((sendme_cell_t*)inp); } +int +sendme_cell_setlen_data_v1_digest(sendme_cell_t *inp, size_t newlen) +{ + uint8_t *newptr; + newptr = trunnel_dynarray_setlen(&inp->data_v1_digest.allocated_, + &inp->data_v1_digest.n_, inp->data_v1_digest.elts_, newlen, + sizeof(inp->data_v1_digest.elts_[0]), (trunnel_free_fn_t) NULL, + &inp->trunnel_error_code_); + if (newlen != 0 && newptr == NULL) + goto trunnel_alloc_failed; + inp->data_v1_digest.elts_ = newptr; + return 0; + trunnel_alloc_failed: + TRUNNEL_SET_ERROR_CODE(inp); + return -1; +} const char * sendme_cell_check(const sendme_cell_t *obj) { @@ -126,6 +156,8 @@ return "A set function failed on this object"; if (! (obj->version == 0 || obj->version == 1)) return "Integer out of bounds"; + if (! (obj->data_len == 16 || obj->data_len == 20)) + return "Integer out of bounds"; switch (obj->version) { case 0: @@ -153,7 +185,7 @@ /* Length of u8 version IN [0, 1] */ result += 1; - /* Length of u16 data_len */ + /* Length of u16 data_len IN [16, 20] */ result += 2; switch (obj->version) { @@ -162,8 +194,8 @@ case 1: - /* Length of u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */ - result += TRUNNEL_SENDME_V1_DIGEST_LEN; + /* Length of u8 data_v1_digest[] */ + result += TRUNNEL_DYNARRAY_LEN(&obj->data_v1_digest); break; default: @@ -206,7 +238,7 @@ trunnel_set_uint8(ptr, (obj->version)); written += 1; ptr += 1; - /* Encode u16 data_len */ + /* Encode u16 data_len IN [16, 20] */ backptr_data_len = ptr; trunnel_assert(written <= avail); if (avail - written < 2) @@ -225,12 +257,16 @@ case 1: - /* Encode u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */ - trunnel_assert(written <= avail); - if (avail - written < TRUNNEL_SENDME_V1_DIGEST_LEN) - goto truncated; - memcpy(ptr, obj->data_v1_digest, TRUNNEL_SENDME_V1_DIGEST_LEN); - written += TRUNNEL_SENDME_V1_DIGEST_LEN; ptr += TRUNNEL_SENDME_V1_DIGEST_LEN; + /* Encode u8 data_v1_digest[] */ + { + size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->data_v1_digest); + trunnel_assert(written <= avail); + if (avail - written < elt_len) + goto truncated; + if (elt_len) + memcpy(ptr, obj->data_v1_digest.elts_, elt_len); + written += elt_len; ptr += elt_len; + } break; default: @@ -287,10 +323,12 @@ if (! (obj->version == 0 || obj->version == 1)) goto fail; - /* Parse u16 data_len */ + /* Parse u16 data_len IN [16, 20] */ CHECK_REMAINING(2, truncated); obj->data_len = trunnel_ntohs(trunnel_get_uint16(ptr)); remaining -= 2; ptr += 2; + if (! (obj->data_len == 16 || obj->data_len == 20)) + goto fail; { size_t remaining_after; CHECK_REMAINING(obj->data_len, truncated); @@ -307,10 +345,12 @@ case 1: - /* Parse u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */ - CHECK_REMAINING(TRUNNEL_SENDME_V1_DIGEST_LEN, fail); - memcpy(obj->data_v1_digest, ptr, TRUNNEL_SENDME_V1_DIGEST_LEN); - remaining -= TRUNNEL_SENDME_V1_DIGEST_LEN; ptr += TRUNNEL_SENDME_V1_DIGEST_LEN; + /* Parse u8 data_v1_digest[] */ + TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->data_v1_digest, remaining, {}); + obj->data_v1_digest.n_ = remaining; + if (remaining) + memcpy(obj->data_v1_digest.elts_, ptr, remaining); + ptr += remaining; remaining -= remaining; break; default: @@ -326,6 +366,8 @@ truncated: return -2; + trunnel_alloc_failed: + return -1; fail: result = -1; return result; diff -Nru tor-0.4.8.16/src/trunnel/sendme_cell.h tor-0.4.9.6/src/trunnel/sendme_cell.h --- tor-0.4.8.16/src/trunnel/sendme_cell.h 2025-03-24 15:23:12.000000000 +0000 +++ tor-0.4.9.6/src/trunnel/sendme_cell.h 2026-03-25 14:30:34.000000000 +0000 @@ -8,12 +8,11 @@ #include #include "trunnel.h" -#define TRUNNEL_SENDME_V1_DIGEST_LEN 20 #if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_SENDME_CELL) struct sendme_cell_st { uint8_t version; uint16_t data_len; - uint8_t data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN]; + TRUNNEL_DYNARRAY_HEAD(, uint8_t) data_v1_digest; uint8_t trunnel_error_code_; }; #endif @@ -71,11 +70,11 @@ * 'inp' on failure. */ int sendme_cell_set_data_len(sendme_cell_t *inp, uint16_t val); -/** Return the (constant) length of the array holding the - * data_v1_digest field of the sendme_cell_t in 'inp'. +/** Return the length of the dynamic array holding the data_v1_digest + * field of the sendme_cell_t in 'inp'. */ size_t sendme_cell_getlen_data_v1_digest(const sendme_cell_t *inp); -/** Return the element at position 'idx' of the fixed array field +/** Return the element at position 'idx' of the dynamic array field * data_v1_digest of the sendme_cell_t in 'inp'. */ uint8_t sendme_cell_get_data_v1_digest(sendme_cell_t *inp, size_t idx); @@ -83,19 +82,29 @@ * pointer */ uint8_t sendme_cell_getconst_data_v1_digest(const sendme_cell_t *inp, size_t idx); -/** Change the element at position 'idx' of the fixed array field +/** Change the element at position 'idx' of the dynamic array field * data_v1_digest of the sendme_cell_t in 'inp', so that it will hold * the value 'elt'. */ int sendme_cell_set_data_v1_digest(sendme_cell_t *inp, size_t idx, uint8_t elt); -/** Return a pointer to the TRUNNEL_SENDME_V1_DIGEST_LEN-element array - * field data_v1_digest of 'inp'. +/** Append a new element 'elt' to the dynamic array field + * data_v1_digest of the sendme_cell_t in 'inp'. + */ +int sendme_cell_add_data_v1_digest(sendme_cell_t *inp, uint8_t elt); +/** Return a pointer to the variable-length array field data_v1_digest + * of 'inp'. */ uint8_t * sendme_cell_getarray_data_v1_digest(sendme_cell_t *inp); /** As sendme_cell_get_data_v1_digest, but take and return a const * pointer */ const uint8_t * sendme_cell_getconstarray_data_v1_digest(const sendme_cell_t *inp); +/** Change the length of the variable-length array field + * data_v1_digest of 'inp' to 'newlen'.Fill extra elements with 0. + * Return 0 on success; return -1 and set the error code on 'inp' on + * failure. + */ +int sendme_cell_setlen_data_v1_digest(sendme_cell_t *inp, size_t newlen); #endif diff -Nru tor-0.4.8.16/src/trunnel/subproto_request.c tor-0.4.9.6/src/trunnel/subproto_request.c --- tor-0.4.8.16/src/trunnel/subproto_request.c 1970-01-01 00:00:00.000000000 +0000 +++ tor-0.4.9.6/src/trunnel/subproto_request.c 2026-03-25 14:30:34.000000000 +0000 @@ -0,0 +1,456 @@ +/* subproto_request.c -- generated by Trunnel v1.5.3. + * https://gitweb.torproject.org/trunnel.git + * You probably shouldn't edit this file. + */ +#include +#include "trunnel-impl.h" + +#include "subproto_request.h" + +#define TRUNNEL_SET_ERROR_CODE(obj) \ + do { \ + (obj)->trunnel_error_code_ = 1; \ + } while (0) + +#if defined(__COVERITY__) || defined(__clang_analyzer__) +/* If we're running a static analysis tool, we don't want it to complain + * that some of our remaining-bytes checks are dead-code. */ +int subprotorequest_deadcode_dummy__ = 0; +#define OR_DEADCODE_DUMMY || subprotorequest_deadcode_dummy__ +#else +#define OR_DEADCODE_DUMMY +#endif + +#define CHECK_REMAINING(nbytes, label) \ + do { \ + if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \ + goto label; \ + } \ + } while (0) + +trn_subproto_request_t * +trn_subproto_request_new(void) +{ + trn_subproto_request_t *val = trunnel_calloc(1, sizeof(trn_subproto_request_t)); + if (NULL == val) + return NULL; + return val; +} + +/** Release all storage held inside 'obj', but do not free 'obj'. + */ +static void +trn_subproto_request_clear(trn_subproto_request_t *obj) +{ + (void) obj; +} + +void +trn_subproto_request_free(trn_subproto_request_t *obj) +{ + if (obj == NULL) + return; + trn_subproto_request_clear(obj); + trunnel_memwipe(obj, sizeof(trn_subproto_request_t)); + trunnel_free_(obj); +} + +uint8_t +trn_subproto_request_get_protocol_id(const trn_subproto_request_t *inp) +{ + return inp->protocol_id; +} +int +trn_subproto_request_set_protocol_id(trn_subproto_request_t *inp, uint8_t val) +{ + inp->protocol_id = val; + return 0; +} +uint8_t +trn_subproto_request_get_proto_cap_number(const trn_subproto_request_t *inp) +{ + return inp->proto_cap_number; +} +int +trn_subproto_request_set_proto_cap_number(trn_subproto_request_t *inp, uint8_t val) +{ + inp->proto_cap_number = val; + return 0; +} +const char * +trn_subproto_request_check(const trn_subproto_request_t *obj) +{ + if (obj == NULL) + return "Object was NULL"; + if (obj->trunnel_error_code_) + return "A set function failed on this object"; + return NULL; +} + +ssize_t +trn_subproto_request_encoded_len(const trn_subproto_request_t *obj) +{ + ssize_t result = 0; + + if (NULL != trn_subproto_request_check(obj)) + return -1; + + + /* Length of u8 protocol_id */ + result += 1; + + /* Length of u8 proto_cap_number */ + result += 1; + return result; +} +int +trn_subproto_request_clear_errors(trn_subproto_request_t *obj) +{ + int r = obj->trunnel_error_code_; + obj->trunnel_error_code_ = 0; + return r; +} +ssize_t +trn_subproto_request_encode(uint8_t *output, const size_t avail, const trn_subproto_request_t *obj) +{ + ssize_t result = 0; + size_t written = 0; + uint8_t *ptr = output; + const char *msg; +#ifdef TRUNNEL_CHECK_ENCODED_LEN + const ssize_t encoded_len = trn_subproto_request_encoded_len(obj); +#endif + + if (NULL != (msg = trn_subproto_request_check(obj))) + goto check_failed; + +#ifdef TRUNNEL_CHECK_ENCODED_LEN + trunnel_assert(encoded_len >= 0); +#endif + + /* Encode u8 protocol_id */ + trunnel_assert(written <= avail); + if (avail - written < 1) + goto truncated; + trunnel_set_uint8(ptr, (obj->protocol_id)); + written += 1; ptr += 1; + + /* Encode u8 proto_cap_number */ + trunnel_assert(written <= avail); + if (avail - written < 1) + goto truncated; + trunnel_set_uint8(ptr, (obj->proto_cap_number)); + written += 1; ptr += 1; + + + trunnel_assert(ptr == output + written); +#ifdef TRUNNEL_CHECK_ENCODED_LEN + { + trunnel_assert(encoded_len >= 0); + trunnel_assert((size_t)encoded_len == written); + } + +#endif + + return written; + + truncated: + result = -2; + goto fail; + check_failed: + (void)msg; + result = -1; + goto fail; + fail: + trunnel_assert(result < 0); + return result; +} + +/** As trn_subproto_request_parse(), but do not allocate the output + * object. + */ +static ssize_t +trn_subproto_request_parse_into(trn_subproto_request_t *obj, const uint8_t *input, const size_t len_in) +{ + const uint8_t *ptr = input; + size_t remaining = len_in; + ssize_t result = 0; + (void)result; + + /* Parse u8 protocol_id */ + CHECK_REMAINING(1, truncated); + obj->protocol_id = (trunnel_get_uint8(ptr)); + remaining -= 1; ptr += 1; + + /* Parse u8 proto_cap_number */ + CHECK_REMAINING(1, truncated); + obj->proto_cap_number = (trunnel_get_uint8(ptr)); + remaining -= 1; ptr += 1; + trunnel_assert(ptr + remaining == input + len_in); + return len_in - remaining; + + truncated: + return -2; +} + +ssize_t +trn_subproto_request_parse(trn_subproto_request_t **output, const uint8_t *input, const size_t len_in) +{ + ssize_t result; + *output = trn_subproto_request_new(); + if (NULL == *output) + return -1; + result = trn_subproto_request_parse_into(*output, input, len_in); + if (result < 0) { + trn_subproto_request_free(*output); + *output = NULL; + } + return result; +} +trn_subproto_request_ext_t * +trn_subproto_request_ext_new(void) +{ + trn_subproto_request_ext_t *val = trunnel_calloc(1, sizeof(trn_subproto_request_ext_t)); + if (NULL == val) + return NULL; + return val; +} + +/** Release all storage held inside 'obj', but do not free 'obj'. + */ +static void +trn_subproto_request_ext_clear(trn_subproto_request_ext_t *obj) +{ + (void) obj; + { + + unsigned idx; + for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->reqs); ++idx) { + trn_subproto_request_free(TRUNNEL_DYNARRAY_GET(&obj->reqs, idx)); + } + } + TRUNNEL_DYNARRAY_WIPE(&obj->reqs); + TRUNNEL_DYNARRAY_CLEAR(&obj->reqs); +} + +void +trn_subproto_request_ext_free(trn_subproto_request_ext_t *obj) +{ + if (obj == NULL) + return; + trn_subproto_request_ext_clear(obj); + trunnel_memwipe(obj, sizeof(trn_subproto_request_ext_t)); + trunnel_free_(obj); +} + +size_t +trn_subproto_request_ext_getlen_reqs(const trn_subproto_request_ext_t *inp) +{ + return TRUNNEL_DYNARRAY_LEN(&inp->reqs); +} + +struct trn_subproto_request_st * +trn_subproto_request_ext_get_reqs(trn_subproto_request_ext_t *inp, size_t idx) +{ + return TRUNNEL_DYNARRAY_GET(&inp->reqs, idx); +} + + const struct trn_subproto_request_st * +trn_subproto_request_ext_getconst_reqs(const trn_subproto_request_ext_t *inp, size_t idx) +{ + return trn_subproto_request_ext_get_reqs((trn_subproto_request_ext_t*)inp, idx); +} +int +trn_subproto_request_ext_set_reqs(trn_subproto_request_ext_t *inp, size_t idx, struct trn_subproto_request_st * elt) +{ + trn_subproto_request_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->reqs, idx); + if (oldval && oldval != elt) + trn_subproto_request_free(oldval); + return trn_subproto_request_ext_set0_reqs(inp, idx, elt); +} +int +trn_subproto_request_ext_set0_reqs(trn_subproto_request_ext_t *inp, size_t idx, struct trn_subproto_request_st * elt) +{ + TRUNNEL_DYNARRAY_SET(&inp->reqs, idx, elt); + return 0; +} +int +trn_subproto_request_ext_add_reqs(trn_subproto_request_ext_t *inp, struct trn_subproto_request_st * elt) +{ + TRUNNEL_DYNARRAY_ADD(struct trn_subproto_request_st *, &inp->reqs, elt, {}); + return 0; + trunnel_alloc_failed: + TRUNNEL_SET_ERROR_CODE(inp); + return -1; +} + +struct trn_subproto_request_st * * +trn_subproto_request_ext_getarray_reqs(trn_subproto_request_ext_t *inp) +{ + return inp->reqs.elts_; +} +const struct trn_subproto_request_st * const * +trn_subproto_request_ext_getconstarray_reqs(const trn_subproto_request_ext_t *inp) +{ + return (const struct trn_subproto_request_st * const *)trn_subproto_request_ext_getarray_reqs((trn_subproto_request_ext_t*)inp); +} +int +trn_subproto_request_ext_setlen_reqs(trn_subproto_request_ext_t *inp, size_t newlen) +{ + struct trn_subproto_request_st * *newptr; + newptr = trunnel_dynarray_setlen(&inp->reqs.allocated_, + &inp->reqs.n_, inp->reqs.elts_, newlen, + sizeof(inp->reqs.elts_[0]), (trunnel_free_fn_t) trn_subproto_request_free, + &inp->trunnel_error_code_); + if (newlen != 0 && newptr == NULL) + goto trunnel_alloc_failed; + inp->reqs.elts_ = newptr; + return 0; + trunnel_alloc_failed: + TRUNNEL_SET_ERROR_CODE(inp); + return -1; +} +const char * +trn_subproto_request_ext_check(const trn_subproto_request_ext_t *obj) +{ + if (obj == NULL) + return "Object was NULL"; + if (obj->trunnel_error_code_) + return "A set function failed on this object"; + { + const char *msg; + + unsigned idx; + for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->reqs); ++idx) { + if (NULL != (msg = trn_subproto_request_check(TRUNNEL_DYNARRAY_GET(&obj->reqs, idx)))) + return msg; + } + } + return NULL; +} + +ssize_t +trn_subproto_request_ext_encoded_len(const trn_subproto_request_ext_t *obj) +{ + ssize_t result = 0; + + if (NULL != trn_subproto_request_ext_check(obj)) + return -1; + + + /* Length of struct trn_subproto_request reqs[] */ + { + + unsigned idx; + for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->reqs); ++idx) { + result += trn_subproto_request_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->reqs, idx)); + } + } + return result; +} +int +trn_subproto_request_ext_clear_errors(trn_subproto_request_ext_t *obj) +{ + int r = obj->trunnel_error_code_; + obj->trunnel_error_code_ = 0; + return r; +} +ssize_t +trn_subproto_request_ext_encode(uint8_t *output, const size_t avail, const trn_subproto_request_ext_t *obj) +{ + ssize_t result = 0; + size_t written = 0; + uint8_t *ptr = output; + const char *msg; +#ifdef TRUNNEL_CHECK_ENCODED_LEN + const ssize_t encoded_len = trn_subproto_request_ext_encoded_len(obj); +#endif + + if (NULL != (msg = trn_subproto_request_ext_check(obj))) + goto check_failed; + +#ifdef TRUNNEL_CHECK_ENCODED_LEN + trunnel_assert(encoded_len >= 0); +#endif + + /* Encode struct trn_subproto_request reqs[] */ + { + + unsigned idx; + for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->reqs); ++idx) { + trunnel_assert(written <= avail); + result = trn_subproto_request_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->reqs, idx)); + if (result < 0) + goto fail; /* XXXXXXX !*/ + written += result; ptr += result; + } + } + + + trunnel_assert(ptr == output + written); +#ifdef TRUNNEL_CHECK_ENCODED_LEN + { + trunnel_assert(encoded_len >= 0); + trunnel_assert((size_t)encoded_len == written); + } + +#endif + + return written; + + check_failed: + (void)msg; + result = -1; + goto fail; + fail: + trunnel_assert(result < 0); + return result; +} + +/** As trn_subproto_request_ext_parse(), but do not allocate the + * output object. + */ +static ssize_t +trn_subproto_request_ext_parse_into(trn_subproto_request_ext_t *obj, const uint8_t *input, const size_t len_in) +{ + const uint8_t *ptr = input; + size_t remaining = len_in; + ssize_t result = 0; + (void)result; + + /* Parse struct trn_subproto_request reqs[] */ + { + trn_subproto_request_t * elt; + while (remaining > 0) { + result = trn_subproto_request_parse(&elt, ptr, remaining); + if (result < 0) + goto fail; + trunnel_assert((size_t)result <= remaining); + remaining -= result; ptr += result; + TRUNNEL_DYNARRAY_ADD(trn_subproto_request_t *, &obj->reqs, elt, {trn_subproto_request_free(elt);}); + } + } + trunnel_assert(ptr + remaining == input + len_in); + return len_in - remaining; + + trunnel_alloc_failed: + return -1; + fail: + result = -1; + return result; +} + +ssize_t +trn_subproto_request_ext_parse(trn_subproto_request_ext_t **output, const uint8_t *input, const size_t len_in) +{ + ssize_t result; + *output = trn_subproto_request_ext_new(); + if (NULL == *output) + return -1; + result = trn_subproto_request_ext_parse_into(*output, input, len_in); + if (result < 0) { + trn_subproto_request_ext_free(*output); + *output = NULL; + } + return result; +} diff -Nru tor-0.4.8.16/src/trunnel/subproto_request.h tor-0.4.9.6/src/trunnel/subproto_request.h --- tor-0.4.8.16/src/trunnel/subproto_request.h 1970-01-01 00:00:00.000000000 +0000 +++ tor-0.4.9.6/src/trunnel/subproto_request.h 2026-03-25 14:30:34.000000000 +0000 @@ -0,0 +1,157 @@ +/* subproto_request.h -- generated by Trunnel v1.5.3. + * https://gitweb.torproject.org/trunnel.git + * You probably shouldn't edit this file. + */ +#ifndef TRUNNEL_SUBPROTO_REQUEST_H +#define TRUNNEL_SUBPROTO_REQUEST_H + +#include +#include "trunnel.h" + +#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_TRN_SUBPROTO_REQUEST) +struct trn_subproto_request_st { + uint8_t protocol_id; + uint8_t proto_cap_number; + uint8_t trunnel_error_code_; +}; +#endif +typedef struct trn_subproto_request_st trn_subproto_request_t; +#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_TRN_SUBPROTO_REQUEST_EXT) +struct trn_subproto_request_ext_st { + TRUNNEL_DYNARRAY_HEAD(, struct trn_subproto_request_st *) reqs; + uint8_t trunnel_error_code_; +}; +#endif +typedef struct trn_subproto_request_ext_st trn_subproto_request_ext_t; +/** Return a newly allocated trn_subproto_request with all elements + * set to zero. + */ +trn_subproto_request_t *trn_subproto_request_new(void); +/** Release all storage held by the trn_subproto_request in 'victim'. + * (Do nothing if 'victim' is NULL.) + */ +void trn_subproto_request_free(trn_subproto_request_t *victim); +/** Try to parse a trn_subproto_request from the buffer in 'input', + * using up to 'len_in' bytes from the input buffer. On success, + * return the number of bytes consumed and set *output to the newly + * allocated trn_subproto_request_t. On failure, return -2 if the + * input appears truncated, and -1 if the input is otherwise invalid. + */ +ssize_t trn_subproto_request_parse(trn_subproto_request_t **output, const uint8_t *input, const size_t len_in); +/** Return the number of bytes we expect to need to encode the + * trn_subproto_request in 'obj'. On failure, return a negative value. + * Note that this value may be an overestimate, and can even be an + * underestimate for certain unencodeable objects. + */ +ssize_t trn_subproto_request_encoded_len(const trn_subproto_request_t *obj); +/** Try to encode the trn_subproto_request from 'input' into the + * buffer at 'output', using up to 'avail' bytes of the output buffer. + * On success, return the number of bytes used. On failure, return -2 + * if the buffer was not long enough, and -1 if the input was invalid. + */ +ssize_t trn_subproto_request_encode(uint8_t *output, size_t avail, const trn_subproto_request_t *input); +/** Check whether the internal state of the trn_subproto_request in + * 'obj' is consistent. Return NULL if it is, and a short message if + * it is not. + */ +const char *trn_subproto_request_check(const trn_subproto_request_t *obj); +/** Clear any errors that were set on the object 'obj' by its setter + * functions. Return true iff errors were cleared. + */ +int trn_subproto_request_clear_errors(trn_subproto_request_t *obj); +/** Return the value of the protocol_id field of the + * trn_subproto_request_t in 'inp' + */ +uint8_t trn_subproto_request_get_protocol_id(const trn_subproto_request_t *inp); +/** Set the value of the protocol_id field of the + * trn_subproto_request_t in 'inp' to 'val'. Return 0 on success; + * return -1 and set the error code on 'inp' on failure. + */ +int trn_subproto_request_set_protocol_id(trn_subproto_request_t *inp, uint8_t val); +/** Return the value of the proto_cap_number field of the + * trn_subproto_request_t in 'inp' + */ +uint8_t trn_subproto_request_get_proto_cap_number(const trn_subproto_request_t *inp); +/** Set the value of the proto_cap_number field of the + * trn_subproto_request_t in 'inp' to 'val'. Return 0 on success; + * return -1 and set the error code on 'inp' on failure. + */ +int trn_subproto_request_set_proto_cap_number(trn_subproto_request_t *inp, uint8_t val); +/** Return a newly allocated trn_subproto_request_ext with all + * elements set to zero. + */ +trn_subproto_request_ext_t *trn_subproto_request_ext_new(void); +/** Release all storage held by the trn_subproto_request_ext in + * 'victim'. (Do nothing if 'victim' is NULL.) + */ +void trn_subproto_request_ext_free(trn_subproto_request_ext_t *victim); +/** Try to parse a trn_subproto_request_ext from the buffer in + * 'input', using up to 'len_in' bytes from the input buffer. On + * success, return the number of bytes consumed and set *output to the + * newly allocated trn_subproto_request_ext_t. On failure, return -2 + * if the input appears truncated, and -1 if the input is otherwise + * invalid. + */ +ssize_t trn_subproto_request_ext_parse(trn_subproto_request_ext_t **output, const uint8_t *input, const size_t len_in); +/** Return the number of bytes we expect to need to encode the + * trn_subproto_request_ext in 'obj'. On failure, return a negative + * value. Note that this value may be an overestimate, and can even be + * an underestimate for certain unencodeable objects. + */ +ssize_t trn_subproto_request_ext_encoded_len(const trn_subproto_request_ext_t *obj); +/** Try to encode the trn_subproto_request_ext from 'input' into the + * buffer at 'output', using up to 'avail' bytes of the output buffer. + * On success, return the number of bytes used. On failure, return -2 + * if the buffer was not long enough, and -1 if the input was invalid. + */ +ssize_t trn_subproto_request_ext_encode(uint8_t *output, size_t avail, const trn_subproto_request_ext_t *input); +/** Check whether the internal state of the trn_subproto_request_ext + * in 'obj' is consistent. Return NULL if it is, and a short message + * if it is not. + */ +const char *trn_subproto_request_ext_check(const trn_subproto_request_ext_t *obj); +/** Clear any errors that were set on the object 'obj' by its setter + * functions. Return true iff errors were cleared. + */ +int trn_subproto_request_ext_clear_errors(trn_subproto_request_ext_t *obj); +/** Return the length of the dynamic array holding the reqs field of + * the trn_subproto_request_ext_t in 'inp'. + */ +size_t trn_subproto_request_ext_getlen_reqs(const trn_subproto_request_ext_t *inp); +/** Return the element at position 'idx' of the dynamic array field + * reqs of the trn_subproto_request_ext_t in 'inp'. + */ +struct trn_subproto_request_st * trn_subproto_request_ext_get_reqs(trn_subproto_request_ext_t *inp, size_t idx); +/** As trn_subproto_request_ext_get_reqs, but take and return a const + * pointer + */ + const struct trn_subproto_request_st * trn_subproto_request_ext_getconst_reqs(const trn_subproto_request_ext_t *inp, size_t idx); +/** Change the element at position 'idx' of the dynamic array field + * reqs of the trn_subproto_request_ext_t in 'inp', so that it will + * hold the value 'elt'. Free the previous value, if any. + */ +int trn_subproto_request_ext_set_reqs(trn_subproto_request_ext_t *inp, size_t idx, struct trn_subproto_request_st * elt); +/** As trn_subproto_request_ext_set_reqs, but does not free the + * previous value. + */ +int trn_subproto_request_ext_set0_reqs(trn_subproto_request_ext_t *inp, size_t idx, struct trn_subproto_request_st * elt); +/** Append a new element 'elt' to the dynamic array field reqs of the + * trn_subproto_request_ext_t in 'inp'. + */ +int trn_subproto_request_ext_add_reqs(trn_subproto_request_ext_t *inp, struct trn_subproto_request_st * elt); +/** Return a pointer to the variable-length array field reqs of 'inp'. + */ +struct trn_subproto_request_st * * trn_subproto_request_ext_getarray_reqs(trn_subproto_request_ext_t *inp); +/** As trn_subproto_request_ext_get_reqs, but take and return a const + * pointer + */ +const struct trn_subproto_request_st * const * trn_subproto_request_ext_getconstarray_reqs(const trn_subproto_request_ext_t *inp); +/** Change the length of the variable-length array field reqs of 'inp' + * to 'newlen'.Fill extra elements with NULL; free removed elements. + * Return 0 on success; return -1 and set the error code on 'inp' on + * failure. + */ +int trn_subproto_request_ext_setlen_reqs(trn_subproto_request_ext_t *inp, size_t newlen); + + +#endif