summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore10
-rw-r--r--ChangeLog203
-rw-r--r--LICENSE32
-rw-r--r--Makefile.am1
-rw-r--r--ReleaseNotes44
-rw-r--r--changes/132955
-rw-r--r--changes/bug108166
-rw-r--r--changes/bug116793
-rw-r--r--changes/bug122264
-rw-r--r--changes/bug126933
-rw-r--r--changes/bug129715
-rw-r--r--changes/bug130964
-rw-r--r--changes/bug131003
-rw-r--r--changes/bug131044
-rw-r--r--changes/bug131248
-rw-r--r--changes/bug13151-client13
-rw-r--r--changes/bug131525
-rw-r--r--changes/bug13161-test-network-echo-n3
-rw-r--r--changes/bug13163-bitwise-check-BRIDGE-DIRINFO5
-rw-r--r--changes/bug13163-stop-AlternateAuthorities-always-using-default-authorities4
-rw-r--r--changes/bug13196-systemd-writable-run-directory3
-rw-r--r--changes/bug132055
-rw-r--r--changes/bug132134
-rw-r--r--changes/bug132285
-rw-r--r--changes/bug13285-disable-curve25519-build-errors3
-rw-r--r--changes/bug13290-avoid-div-zero-circuitstatus-pareto5
-rw-r--r--changes/bug13291-spawn-test-race-condition4
-rw-r--r--changes/bug133144
-rw-r--r--changes/bug133254
-rw-r--r--changes/bug13331-make-j2-test-network-hang3
-rw-r--r--changes/bug13393-format-time-interval-overflow-test6
-rw-r--r--changes/bug134715
-rw-r--r--changes/bug13476-improve-time-handling20
-rw-r--r--changes/bug13477-memwipe-more-keys5
-rw-r--r--changes/bug42446
-rw-r--r--changes/bug7733a4
-rw-r--r--changes/bug80933
-rw-r--r--changes/bug81976
-rw-r--r--changes/bug84025
-rw-r--r--changes/disable_sslv34
-rw-r--r--changes/feature131535
-rw-r--r--changes/feature13161-TestingDirAuthVoteExit7
-rw-r--r--changes/feature13161-test-network-delay-option4
-rw-r--r--changes/feature132116
-rw-r--r--changes/issue13163-improve-DIRINFO-flags-comments5
-rw-r--r--changes/issue13284-spurious-clang-shallow-analyze-errors3
-rw-r--r--changes/require-c9910
-rw-r--r--changes/ticket111448
-rw-r--r--changes/ticket112437
-rw-r--r--changes/ticket115825
-rw-r--r--changes/ticket128843
-rw-r--r--changes/ticket9615
-rw-r--r--changes/ticket_131196
-rw-r--r--configure.ac49
-rw-r--r--contrib/dist/tor.service.in1
-rw-r--r--doc/HACKING33
-rw-r--r--doc/tor.1.txt59
-rw-r--r--scripts/coccinelle/malloc_cast.cocci38
-rw-r--r--scripts/coccinelle/uncalloc.cocci13
-rw-r--r--scripts/codegen/makedesc.py218
-rwxr-xr-xscripts/codegen/run_trunnel.sh11
-rwxr-xr-xscripts/maint/format_changelog.py133
-rwxr-xr-xscripts/test/cov-diff4
-rw-r--r--src/common/address.c19
-rw-r--r--src/common/address.h13
-rw-r--r--src/common/compat.c18
-rw-r--r--src/common/compat_libevent.c3
-rw-r--r--src/common/crypto.c52
-rw-r--r--src/common/crypto.h6
-rw-r--r--src/common/crypto_curve25519.c176
-rw-r--r--src/common/crypto_curve25519.h14
-rw-r--r--src/common/crypto_ed25519.c353
-rw-r--r--src/common/crypto_ed25519.h116
-rw-r--r--src/common/crypto_format.c22
-rw-r--r--src/common/crypto_pwbox.c187
-rw-r--r--src/common/crypto_pwbox.h20
-rw-r--r--src/common/crypto_s2k.c460
-rw-r--r--src/common/crypto_s2k.h73
-rw-r--r--src/common/include.am15
-rw-r--r--src/common/sandbox.c21
-rw-r--r--src/common/sandbox.h2
-rw-r--r--src/common/tortls.c57
-rw-r--r--src/common/util.c105
-rw-r--r--src/config/include.am2
-rw-r--r--src/config/torrc.minimal.in192
-rw-r--r--src/config/torrc.minimal.in-staging193
-rw-r--r--src/config/torrc.sample.in17
-rw-r--r--src/ext/README12
-rw-r--r--src/ext/ed25519/ref10/Makefile41
-rw-r--r--src/ext/ed25519/ref10/README.tor23
-rw-r--r--src/ext/ed25519/ref10/api.h4
-rw-r--r--src/ext/ed25519/ref10/base.h1344
-rw-r--r--src/ext/ed25519/ref10/base.py65
-rw-r--r--src/ext/ed25519/ref10/base2.h40
-rw-r--r--src/ext/ed25519/ref10/base2.py60
-rw-r--r--src/ext/ed25519/ref10/blinding.c76
-rw-r--r--src/ext/ed25519/ref10/crypto_hash_sha512.h30
-rw-r--r--src/ext/ed25519/ref10/crypto_int32.h25
-rw-r--r--src/ext/ed25519/ref10/crypto_int64.h23
-rw-r--r--src/ext/ed25519/ref10/crypto_sign.h9
-rw-r--r--src/ext/ed25519/ref10/crypto_uint32.h3
-rw-r--r--src/ext/ed25519/ref10/crypto_uint64.h3
-rw-r--r--src/ext/ed25519/ref10/crypto_verify_32.h5
-rw-r--r--src/ext/ed25519/ref10/d.h1
-rw-r--r--src/ext/ed25519/ref10/d.py28
-rw-r--r--src/ext/ed25519/ref10/d2.h1
-rw-r--r--src/ext/ed25519/ref10/d2.py28
-rw-r--r--src/ext/ed25519/ref10/ed25519_ref10.h30
-rw-r--r--src/ext/ed25519/ref10/fe.h56
-rw-r--r--src/ext/ed25519/ref10/fe_0.c19
-rw-r--r--src/ext/ed25519/ref10/fe_1.c19
-rw-r--r--src/ext/ed25519/ref10/fe_add.c57
-rw-r--r--src/ext/ed25519/ref10/fe_cmov.c63
-rw-r--r--src/ext/ed25519/ref10/fe_copy.c29
-rw-r--r--src/ext/ed25519/ref10/fe_frombytes.c73
-rw-r--r--src/ext/ed25519/ref10/fe_invert.c14
-rw-r--r--src/ext/ed25519/ref10/fe_isnegative.c16
-rw-r--r--src/ext/ed25519/ref10/fe_isnonzero.c19
-rw-r--r--src/ext/ed25519/ref10/fe_mul.c253
-rw-r--r--src/ext/ed25519/ref10/fe_neg.c45
-rw-r--r--src/ext/ed25519/ref10/fe_pow22523.c13
-rw-r--r--src/ext/ed25519/ref10/fe_sq.c149
-rw-r--r--src/ext/ed25519/ref10/fe_sq2.c160
-rw-r--r--src/ext/ed25519/ref10/fe_sub.c57
-rw-r--r--src/ext/ed25519/ref10/fe_tobytes.c119
-rw-r--r--src/ext/ed25519/ref10/ge.h95
-rw-r--r--src/ext/ed25519/ref10/ge_add.c11
-rw-r--r--src/ext/ed25519/ref10/ge_add.h97
-rw-r--r--src/ext/ed25519/ref10/ge_add.q49
-rw-r--r--src/ext/ed25519/ref10/ge_double_scalarmult.c96
-rw-r--r--src/ext/ed25519/ref10/ge_frombytes.c50
-rw-r--r--src/ext/ed25519/ref10/ge_madd.c11
-rw-r--r--src/ext/ed25519/ref10/ge_madd.h88
-rw-r--r--src/ext/ed25519/ref10/ge_madd.q46
-rw-r--r--src/ext/ed25519/ref10/ge_msub.c11
-rw-r--r--src/ext/ed25519/ref10/ge_msub.h88
-rw-r--r--src/ext/ed25519/ref10/ge_msub.q46
-rw-r--r--src/ext/ed25519/ref10/ge_p1p1_to_p2.c12
-rw-r--r--src/ext/ed25519/ref10/ge_p1p1_to_p3.c13
-rw-r--r--src/ext/ed25519/ref10/ge_p2_0.c8
-rw-r--r--src/ext/ed25519/ref10/ge_p2_dbl.c11
-rw-r--r--src/ext/ed25519/ref10/ge_p2_dbl.h73
-rw-r--r--src/ext/ed25519/ref10/ge_p2_dbl.q41
-rw-r--r--src/ext/ed25519/ref10/ge_p3_0.c9
-rw-r--r--src/ext/ed25519/ref10/ge_p3_dbl.c12
-rw-r--r--src/ext/ed25519/ref10/ge_p3_to_cached.c17
-rw-r--r--src/ext/ed25519/ref10/ge_p3_to_p2.c12
-rw-r--r--src/ext/ed25519/ref10/ge_p3_tobytes.c14
-rw-r--r--src/ext/ed25519/ref10/ge_precomp_0.c8
-rw-r--r--src/ext/ed25519/ref10/ge_scalarmult_base.c109
-rw-r--r--src/ext/ed25519/ref10/ge_sub.c11
-rw-r--r--src/ext/ed25519/ref10/ge_sub.h97
-rw-r--r--src/ext/ed25519/ref10/ge_sub.q49
-rw-r--r--src/ext/ed25519/ref10/ge_tobytes.c14
-rw-r--r--src/ext/ed25519/ref10/keyconv.c37
-rw-r--r--src/ext/ed25519/ref10/keypair.c51
-rw-r--r--src/ext/ed25519/ref10/open.c42
-rw-r--r--src/ext/ed25519/ref10/pow22523.h161
-rw-r--r--src/ext/ed25519/ref10/pow22523.q61
-rw-r--r--src/ext/ed25519/ref10/pow225521.h161
-rw-r--r--src/ext/ed25519/ref10/pow225521.q61
-rwxr-xr-xsrc/ext/ed25519/ref10/q2h.sh4
-rw-r--r--src/ext/ed25519/ref10/randombytes.h4
-rw-r--r--src/ext/ed25519/ref10/sc.h15
-rw-r--r--src/ext/ed25519/ref10/sc_muladd.c368
-rw-r--r--src/ext/ed25519/ref10/sc_reduce.c275
-rw-r--r--src/ext/ed25519/ref10/sign.c29
-rw-r--r--src/ext/ed25519/ref10/sqrtm1.h1
-rw-r--r--src/ext/ed25519/ref10/sqrtm1.py28
-rw-r--r--src/ext/include.am76
-rw-r--r--src/ext/trunnel/trunnel-impl.h310
-rw-r--r--src/ext/trunnel/trunnel.c246
-rw-r--r--src/ext/trunnel/trunnel.h64
-rw-r--r--src/include.am2
-rw-r--r--src/or/buffers.c31
-rw-r--r--src/or/circuitstats.c18
-rw-r--r--src/or/circuituse.c36
-rw-r--r--src/or/config.c130
-rw-r--r--src/or/config.h1
-rw-r--r--src/or/connection.c44
-rw-r--r--src/or/connection_edge.c4
-rw-r--r--src/or/control.c23
-rw-r--r--src/or/directory.c15
-rw-r--r--src/or/dirserv.c95
-rw-r--r--src/or/dirvote.c6
-rw-r--r--src/or/entrynodes.c20
-rw-r--r--src/or/hibernate.c51
-rw-r--r--src/or/hibernate.h1
-rw-r--r--src/or/main.c9
-rw-r--r--src/or/microdesc.c50
-rw-r--r--src/or/networkstatus.c40
-rw-r--r--src/or/networkstatus.h17
-rw-r--r--src/or/or.h23
-rw-r--r--src/or/policies.c86
-rw-r--r--src/or/policies.h14
-rw-r--r--src/or/relay.c2
-rw-r--r--src/or/rendclient.c2
-rw-r--r--src/or/rendcommon.c4
-rw-r--r--src/or/rendmid.c4
-rw-r--r--src/or/rendservice.c2
-rw-r--r--src/or/router.c21
-rw-r--r--src/or/routerlist.c111
-rw-r--r--src/or/routerlist.h18
-rw-r--r--src/or/routerparse.c92
-rw-r--r--src/or/routerparse.h12
-rw-r--r--src/or/status.c6
-rw-r--r--src/or/transports.c113
-rw-r--r--src/or/transports.h6
-rw-r--r--src/test/bench.c62
-rw-r--r--src/test/ed25519_exts_ref.py234
-rw-r--r--src/test/ed25519_vectors.inc150
-rw-r--r--src/test/example_extrainfo.inc192
-rw-r--r--src/test/failing_routerdescs.inc668
-rw-r--r--src/test/include.am8
-rw-r--r--src/test/slow_ed25519.py115
-rwxr-xr-xsrc/test/test-network.sh17
-rw-r--r--src/test/test.c303
-rw-r--r--src/test/test.h24
-rw-r--r--src/test/test_accounting.c76
-rw-r--r--src/test/test_addr.c424
-rw-r--r--src/test/test_buffers.c110
-rw-r--r--src/test/test_cell_formats.c72
-rw-r--r--src/test/test_cell_queue.c8
-rw-r--r--src/test/test_circuitlist.c2
-rw-r--r--src/test/test_circuitmux.c2
-rw-r--r--src/test/test_config.c142
-rw-r--r--src/test/test_containers.c485
-rw-r--r--src/test/test_crypto.c1065
-rw-r--r--src/test/test_dir.c1455
-rw-r--r--src/test/test_entrynodes.c14
-rw-r--r--src/test/test_extorport.c36
-rw-r--r--src/test/test_hs.c16
-rw-r--r--src/test/test_introduce.c76
-rw-r--r--src/test/test_microdesc.c359
-rw-r--r--src/test/test_nodelist.c6
-rw-r--r--src/test/test_policy.c126
-rw-r--r--src/test/test_pt.c156
-rw-r--r--src/test/test_replay.c119
-rw-r--r--src/test/test_routerset.c14
-rw-r--r--src/test/test_socks.c354
-rw-r--r--src/test/test_util.c2717
-rw-r--r--src/tools/tor-resolve.c2
-rw-r--r--src/trunnel/include.am29
-rw-r--r--src/trunnel/pwbox.c515
-rw-r--r--src/trunnel/pwbox.h173
-rw-r--r--src/trunnel/pwbox.trunnel14
-rw-r--r--src/trunnel/trunnel-local.h18
247 files changed, 17696 insertions, 3213 deletions
diff --git a/.gitignore b/.gitignore
index 1a479903dc..9ddd0c5385 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,7 @@ cscope.*
/mkinstalldirs
/Tor*Bundle.dmg
/tor-*-win32.exe
+/coverage_html/
# /contrib/
/contrib/dist/tor.sh
@@ -135,6 +136,11 @@ cscope.*
/src/config/sample-server-torrc
/src/config/torrc
/src/config/torrc.sample
+/src/config/torrc.minimal
+
+# /src/ext/
+/src/ext/ed25519/ref10/libed25519_ref10.a
+/src/ext/ed25519/ref10/libed25519_ref10.lib
# /src/or/
/src/or/Makefile
@@ -172,6 +178,10 @@ cscope.*
/src/tools/Makefile
/src/tools/Makefile.in
+# /src/trunnel/
+/src/trunnel/libor-trunnel-testing.a
+/src/trunnel/libor-trunnel.a
+
# /src/tools/tor-fw-helper/
/src/tools/tor-fw-helper/tor-fw-helper
/src/tools/tor-fw-helper/tor-fw-helper.exe
diff --git a/ChangeLog b/ChangeLog
index 688d6554ff..6e466a418f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,209 @@
Changes in version 0.2.6.1-alpha - 2014-??-??
+Changes in version 0.2.5.9-rc - 2014-10-20
+ Tor 0.2.5.9-rc is the third release candidate for the Tor 0.2.5.x
+ series. It disables SSL3 in response to the recent "POODLE" attack
+ (even though POODLE does not affect Tor). It also works around a crash
+ bug caused by some operating systems' response to the "POODLE" attack
+ (which does affect Tor). It also contains a few miscellaneous fixes.
+
+ o Major security fixes:
+ - Disable support for SSLv3. All versions of OpenSSL in use with Tor
+ today support TLS 1.0 or later, so we can safely turn off support
+ for this old (and insecure) protocol. Fixes bug 13426.
+
+ o Major bugfixes (openssl bug workaround):
+ - Avoid crashing when using OpenSSL version 0.9.8zc, 1.0.0o, or
+ 1.0.1j, built with the 'no-ssl3' configuration option. Fixes bug
+ 13471. This is a workaround for an OpenSSL bug.
+
+ o Minor bugfixes:
+ - Disable the sandbox name resolver cache when running tor-resolve:
+ tor-resolve doesn't use the sandbox code, and turning it on was
+ breaking attempts to do tor-resolve on a non-default server on
+ Linux. Fixes bug 13295; bugfix on 0.2.5.3-alpha.
+
+ o Compilation fixes:
+ - Build and run correctly on systems like OpenBSD-current that have
+ patched OpenSSL to remove get_cipher_by_char and/or its
+ implementations. Fixes issue 13325.
+
+ o Downgraded warnings:
+ - Downgrade the severity of the 'unexpected sendme cell from client'
+ from 'warn' to 'protocol warning'. Closes ticket 8093.
+
+
+Changes in version 0.2.4.25 - 2014-10-20
+ Tor 0.2.4.25 disables SSL3 in response to the recent "POODLE" attack
+ (even though POODLE does not affect Tor). It also works around a crash
+ bug caused by some operating systems' response to the "POODLE" attack
+ (which does affect Tor).
+
+ o Major security fixes (also in 0.2.5.9-rc):
+ - Disable support for SSLv3. All versions of OpenSSL in use with Tor
+ today support TLS 1.0 or later, so we can safely turn off support
+ for this old (and insecure) protocol. Fixes bug 13426.
+
+ o Major bugfixes (openssl bug workaround, also in 0.2.5.9-rc):
+ - Avoid crashing when using OpenSSL version 0.9.8zc, 1.0.0o, or
+ 1.0.1j, built with the 'no-ssl3' configuration option. Fixes bug
+ 13471. This is a workaround for an OpenSSL bug.
+
+
+Changes in version 0.2.5.8-rc - 2014-09-22
+ Tor 0.2.5.8-rc is the second release candidate for the Tor 0.2.5.x
+ series. It fixes a bug that affects consistency and speed when
+ connecting to hidden services, and it updates the location of one of
+ the directory authorities.
+
+ o Major bugfixes:
+ - Clients now send the correct address for their chosen rendezvous
+ point when trying to access a hidden service. They used to send
+ the wrong address, which would still work some of the time because
+ they also sent the identity digest of the rendezvous point, and if
+ the hidden service happened to try connecting to the rendezvous
+ point from a relay that already had a connection open to it,
+ the relay would reuse that connection. Now connections to hidden
+ services should be more robust and faster. Also, this bug meant
+ that clients were leaking to the hidden service whether they were
+ on a little-endian (common) or big-endian (rare) system, which for
+ some users might have reduced their anonymity. Fixes bug 13151;
+ bugfix on 0.2.1.5-alpha.
+
+ o Directory authority changes:
+ - Change IP address for gabelmoo (v3 directory authority).
+
+
+Changes in version 0.2.4.24 - 2014-09-22
+ Tor 0.2.4.24 fixes a bug that affects consistency and speed when
+ connecting to hidden services, and it updates the location of one of
+ the directory authorities.
+
+ o Major bugfixes:
+ - Clients now send the correct address for their chosen rendezvous
+ point when trying to access a hidden service. They used to send
+ the wrong address, which would still work some of the time because
+ they also sent the identity digest of the rendezvous point, and if
+ the hidden service happened to try connecting to the rendezvous
+ point from a relay that already had a connection open to it,
+ the relay would reuse that connection. Now connections to hidden
+ services should be more robust and faster. Also, this bug meant
+ that clients were leaking to the hidden service whether they were
+ on a little-endian (common) or big-endian (rare) system, which for
+ some users might have reduced their anonymity. Fixes bug 13151;
+ bugfix on 0.2.1.5-alpha.
+
+ o Directory authority changes:
+ - Change IP address for gabelmoo (v3 directory authority).
+
+ o Minor features (geoip):
+ - Update geoip and geoip6 to the August 7 2014 Maxmind GeoLite2
+ Country database.
+
+
+Changes in version 0.2.5.7-rc - 2014-09-11
+ Tor 0.2.5.7-rc fixes several regressions from earlier in the 0.2.5.x
+ release series, and some long-standing bugs related to ORPort reachability
+ testing and failure to send CREATE cells. It is the first release
+ candidate for the Tor 0.2.5.x series.
+
+ o Major bugfixes (client, startup):
+ - Start making circuits as soon as DisabledNetwork is turned off.
+ When Tor started with DisabledNetwork set, it would correctly
+ conclude that it shouldn't build circuits, but it would mistakenly
+ cache this conclusion, and continue believing it even when
+ DisableNetwork is set to 0. Fixes the bug introduced by the fix
+ for bug 11200; bugfix on 0.2.5.4-alpha.
+ - Resume expanding abbreviations for command-line options. The fix
+ for bug 4647 accidentally removed our hack from bug 586 that
+ rewrote HashedControlPassword to __HashedControlSessionPassword
+ when it appears on the commandline (which allowed the user to set
+ her own HashedControlPassword in the torrc file while the
+ controller generates a fresh session password for each run). Fixes
+ bug 12948; bugfix on 0.2.5.1-alpha.
+ - Warn about attempts to run hidden services and relays in the same
+ process: that's probably not a good idea. Closes ticket 12908.
+
+ o Major bugfixes (relay):
+ - Avoid queuing or sending destroy cells for circuit ID zero when we
+ fail to send a CREATE cell. Fixes bug 12848; bugfix on 0.0.8pre1.
+ Found and fixed by "cypherpunks".
+ - Fix ORPort reachability detection on relays running behind a
+ proxy, by correctly updating the "local" mark on the controlling
+ channel when changing the address of an or_connection_t after the
+ handshake. Fixes bug 12160; bugfix on 0.2.4.4-alpha.
+
+ o Minor features (bridge):
+ - Add an ExtORPortCookieAuthFileGroupReadable option to make the
+ cookie file for the ExtORPort g+r by default.
+
+ o Minor features (geoip):
+ - Update geoip and geoip6 to the August 7 2014 Maxmind GeoLite2
+ Country database.
+
+ o Minor bugfixes (logging):
+ - Reduce the log severity of the "Pluggable transport proxy does not
+ provide any needed transports and will not be launched." message,
+ since Tor Browser includes several ClientTransportPlugin lines in
+ its torrc-defaults file, leading every Tor Browser user who looks
+ at her logs to see these notices and wonder if they're dangerous.
+ Resolves bug 13124; bugfix on 0.2.5.3-alpha.
+ - Downgrade "Unexpected onionskin length after decryption" warning
+ to a protocol-warn, since there's nothing relay operators can do
+ about a client that sends them a malformed create cell. Resolves
+ bug 12996; bugfix on 0.0.6rc1.
+ - Log more specific warnings when we get an ESTABLISH_RENDEZVOUS
+ cell on a cannibalized or non-OR circuit. Resolves ticket 12997.
+ - When logging information about an EXTEND2 or EXTENDED2 cell, log
+ their names correctly. Fixes part of bug 12700; bugfix
+ on 0.2.4.8-alpha.
+ - When logging information about a relay cell whose command we don't
+ recognize, log its command as an integer. Fixes part of bug 12700;
+ bugfix on 0.2.1.10-alpha.
+ - Escape all strings from the directory connection before logging
+ them. Fixes bug 13071; bugfix on 0.1.1.15. Patch from "teor".
+
+ o Minor bugfixes (controller):
+ - Restore the functionality of CookieAuthFileGroupReadable. Fixes
+ bug 12864; bugfix on 0.2.5.1-alpha.
+ - Actually send TRANSPORT_LAUNCHED and HS_DESC events to
+ controllers. Fixes bug 13085; bugfix on 0.2.5.1-alpha. Patch
+ by "teor".
+
+ o Minor bugfixes (compilation):
+ - Fix compilation of test.h with MSVC. Patch from Gisle Vanem;
+ bugfix on 0.2.5.5-alpha.
+ - Make the nmake make files work again. Fixes bug 13081. Bugfix on
+ 0.2.5.1-alpha. Patch from "NewEraCracker".
+ - In routerlist_assert_ok(), don't take the address of a
+ routerinfo's cache_info member unless that routerinfo is non-NULL.
+ Fixes bug 13096; bugfix on 0.1.1.9-alpha. Patch by "teor".
+ - Fix a large number of false positive warnings from the clang
+ analyzer static analysis tool. This should make real warnings
+ easier for clang analyzer to find. Patch from "teor". Closes
+ ticket 13036.
+
+ o Distribution (systemd):
+ - Verify configuration file via ExecStartPre in the systemd unit
+ file. Patch from intrigeri; resolves ticket 12730.
+ - Explicitly disable RunAsDaemon in the systemd unit file. Our
+ current systemd unit uses "Type = simple", so systemd does not
+ expect tor to fork. If the user has "RunAsDaemon 1" in their
+ torrc, then things won't work as expected. This is e.g. the case
+ on Debian (and derivatives), since there we pass "--defaults-torrc
+ /usr/share/tor/tor-service-defaults-torrc" (that contains
+ "RunAsDaemon 1") by default. Patch by intrigeri; resolves
+ ticket 12731.
+
+ o Documentation:
+ - Adjust the URLs in the README to refer to the new locations of
+ several documents on the website. Fixes bug 12830. Patch from
+ Matt Pagan.
+ - Document 'reject6' and 'accept6' ExitPolicy entries. Resolves
+ ticket 12878.
+
+
Changes in version 0.2.5.6-alpha - 2014-07-28
Tor 0.2.5.6-alpha brings us a big step closer to slowing down the
risk from guard rotation, and fixes a variety of other issues to get
diff --git a/LICENSE b/LICENSE
index 4ebab1823f..1c753311e9 100644
--- a/LICENSE
+++ b/LICENSE
@@ -122,6 +122,38 @@ src/ext/csiphash.c is licensed under the following license:
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.
+===============================================================================
+Trunnel is distributed under this license:
+
+Copyright 2014 The Tor Project, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+ * Neither the names of the copyright owners nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===============================================================================
src/config/geoip is licensed under the following license:
diff --git a/Makefile.am b/Makefile.am
index 910cb12005..7125c7701c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,7 +23,6 @@ include src/include.am
include doc/include.am
include contrib/include.am
-
EXTRA_DIST+= \
ChangeLog \
INSTALL \
diff --git a/ReleaseNotes b/ReleaseNotes
index 2ad0f1ede5..1d42075694 100644
--- a/ReleaseNotes
+++ b/ReleaseNotes
@@ -3,6 +3,50 @@ This document summarizes new features and bugfixes in each stable 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.2.4.25 - 2014-10-20
+ Tor 0.2.4.25 disables SSL3 in response to the recent "POODLE" attack
+ (even though POODLE does not affect Tor). It also works around a crash
+ bug caused by some operating systems' response to the "POODLE" attack
+ (which does affect Tor).
+
+ o Major security fixes (also in 0.2.5.9-rc):
+ - Disable support for SSLv3. All versions of OpenSSL in use with Tor
+ today support TLS 1.0 or later, so we can safely turn off support
+ for this old (and insecure) protocol. Fixes bug 13426.
+
+ o Major bugfixes (openssl bug workaround, also in 0.2.5.9-rc):
+ - Avoid crashing when using OpenSSL version 0.9.8zc, 1.0.0o, or
+ 1.0.1j, built with the 'no-ssl3' configuration option. Fixes bug
+ 13471. This is a workaround for an OpenSSL bug.
+
+
+Changes in version 0.2.4.24 - 2014-09-22
+ Tor 0.2.4.24 fixes a bug that affects consistency and speed when
+ connecting to hidden services, and it updates the location of one of
+ the directory authorities.
+
+ o Major bugfixes:
+ - Clients now send the correct address for their chosen rendezvous
+ point when trying to access a hidden service. They used to send
+ the wrong address, which would still work some of the time because
+ they also sent the identity digest of the rendezvous point, and if
+ the hidden service happened to try connecting to the rendezvous
+ point from a relay that already had a connection open to it,
+ the relay would reuse that connection. Now connections to hidden
+ services should be more robust and faster. Also, this bug meant
+ that clients were leaking to the hidden service whether they were
+ on a little-endian (common) or big-endian (rare) system, which for
+ some users might have reduced their anonymity. Fixes bug 13151;
+ bugfix on 0.2.1.5-alpha.
+
+ o Directory authority changes:
+ - Change IP address for gabelmoo (v3 directory authority).
+
+ o Minor features (geoip):
+ - Update geoip and geoip6 to the August 7 2014 Maxmind GeoLite2
+ Country database.
+
+
Changes in version 0.2.4.23 - 2014-07-28
Tor 0.2.4.23 brings us a big step closer to slowing down the risk from
guard rotation, and also backports several important fixes from the
diff --git a/changes/13295 b/changes/13295
new file mode 100644
index 0000000000..433432595f
--- /dev/null
+++ b/changes/13295
@@ -0,0 +1,5 @@
+ o Minor bugfixes:
+ - Disable sandbox name resolver cache when running tor-resolve:
+ tor-resolve doesn't use the sandbox code, and turning it on was
+ breaking attempts to do tor-resolve on a non-default server on
+ Linux. Fixes bug 13295; bugfix on 0.2.5.3-alpha.
diff --git a/changes/bug10816 b/changes/bug10816
new file mode 100644
index 0000000000..1185f3c2d6
--- /dev/null
+++ b/changes/bug10816
@@ -0,0 +1,6 @@
+ o Minor bugfixes (windows):
+ - Remove code to special-case handling of NTE_BAD_KEYSET when
+ acquiring windows CryptoAPI context. This error can't actually
+ occur for the parameters we're providing. Fixes bug 10816;
+ bugfix on 0.0.2pre26.
+
diff --git a/changes/bug11679 b/changes/bug11679
new file mode 100644
index 0000000000..3a191ce822
--- /dev/null
+++ b/changes/bug11679
@@ -0,0 +1,3 @@
+ o Minor bugfixes (client):
+ - Use the consensus schedule for downloading consensuses, and not the
+ generic schedule. Fixes bug 11679; bugfix on 0.2.2.6-alpha.
diff --git a/changes/bug12226 b/changes/bug12226
new file mode 100644
index 0000000000..0058b838cd
--- /dev/null
+++ b/changes/bug12226
@@ -0,0 +1,4 @@
+ o Removed features:
+ - The old "StrictEntryNodes" and "StrictExitNodes" options, which
+ used to be deprecated synonyms for "StrictNodes", are now marked
+ obsolete. Resolves ticket 12226.
diff --git a/changes/bug12693 b/changes/bug12693
new file mode 100644
index 0000000000..11dfe78a2f
--- /dev/null
+++ b/changes/bug12693
@@ -0,0 +1,3 @@
+ o Build fixes:
+ - Allow our configure script to build correctly with autoconf 2.62
+ again. Fixes bug 12693; bugfix on 0.2.5.2-alpha.
diff --git a/changes/bug12971 b/changes/bug12971
new file mode 100644
index 0000000000..e548bbfa11
--- /dev/null
+++ b/changes/bug12971
@@ -0,0 +1,5 @@
+ o Bugfixes:
+ - Handle unsupported SOCKS5 requests properly by responding with
+ 'Command not supported' reply message before closing a TCP connection
+ to the user. Fixes bug 12971.
+
diff --git a/changes/bug13096 b/changes/bug13096
new file mode 100644
index 0000000000..521faaf143
--- /dev/null
+++ b/changes/bug13096
@@ -0,0 +1,4 @@
+ o Minor bugfixes (conformance):
+ - In routerlist_assert_ok(), don't take the address of a routerinfo's
+ cache_info member unless that routerinfo is non-NULL. Fixes bug
+ 13096; bugfix on 0.1.1.9-alpha. Patch by "teor".
diff --git a/changes/bug13100 b/changes/bug13100
new file mode 100644
index 0000000000..bbe43e65a7
--- /dev/null
+++ b/changes/bug13100
@@ -0,0 +1,3 @@
+ o Directory authority changes:
+ - Change IP address for gabelmoo (v3 directory authority).
+
diff --git a/changes/bug13104 b/changes/bug13104
new file mode 100644
index 0000000000..331db64ccc
--- /dev/null
+++ b/changes/bug13104
@@ -0,0 +1,4 @@
+ o Minor bugfixes:
+ - Fix several instances of possible integer overflow/underflow/NaN.
+ Fixes bug 13104; bugfix on 0.2.3.1-alpha and later. Patches from
+ "teor".
diff --git a/changes/bug13124 b/changes/bug13124
new file mode 100644
index 0000000000..be7df70347
--- /dev/null
+++ b/changes/bug13124
@@ -0,0 +1,8 @@
+ o Minor bugfixes:
+ - Reduce the log severity of the "Pluggable transport proxy does
+ not provide any needed transports and will not be launched."
+ message, since Tor Browser includes several ClientTransportPlugin
+ lines in its torrc-defaults file, leading every Tor Browser user
+ who looks at her logs to see these notices and wonder if they're
+ dangerous. Resolves bug 13124; bugfix on 0.2.5.3-alpha.
+
diff --git a/changes/bug13151-client b/changes/bug13151-client
new file mode 100644
index 0000000000..1218dfdfab
--- /dev/null
+++ b/changes/bug13151-client
@@ -0,0 +1,13 @@
+ o Major bugfixes:
+ - Clients now send the correct address for their chosen rendezvous
+ point when trying to access a hidden service. They used to send
+ the wrong address, which would still work some of the time because
+ they also sent the identity digest of the rendezvous point, and if
+ the hidden service happened to try connecting to the rendezvous
+ point from a relay that already had a connection open to it,
+ the relay would reuse that connection. Now connections to hidden
+ services should be more robust and faster. Also, this bug meant
+ that clients were leaking to the hidden service whether they were
+ on a little-endian (common) or big-endian (rare) system, which for
+ some users might have reduced their anonymity. Fixes bug 13151;
+ bugfix on 0.2.1.5-alpha.
diff --git a/changes/bug13152 b/changes/bug13152
new file mode 100644
index 0000000000..c6f3d61ad7
--- /dev/null
+++ b/changes/bug13152
@@ -0,0 +1,5 @@
+ o Removed features (directory authority):
+ - Remove code that prevented authorities from listing Tor servers
+ affected by CVE-2011-2769 as guards. These servers are already
+ rejected altogether due to the minimum version requirement of
+ 0.2.3.16-alpha. Closes ticket 13152.
diff --git a/changes/bug13161-test-network-echo-n b/changes/bug13161-test-network-echo-n
new file mode 100644
index 0000000000..501ebdda1f
--- /dev/null
+++ b/changes/bug13161-test-network-echo-n
@@ -0,0 +1,3 @@
+ o Minor bugfixes:
+ - Stop using "echo -n", as some shells' built-in echo doesn't support
+ "-n". Instead, use "/bin/echo -n". Partially fixes bug 13161.
diff --git a/changes/bug13163-bitwise-check-BRIDGE-DIRINFO b/changes/bug13163-bitwise-check-BRIDGE-DIRINFO
new file mode 100644
index 0000000000..7f5ec05037
--- /dev/null
+++ b/changes/bug13163-bitwise-check-BRIDGE-DIRINFO
@@ -0,0 +1,5 @@
+ o Minor bugfixes:
+ - Bitwise check the BRIDGE_DIRINFO flag rather than using equality.
+ Fixes a (potential) bug where directories offering BRIDGE_DIRINFO and
+ some other flag (i.e. microdescriptors or extrainfo) would be ignored
+ when looking for bridge directories. Partially fixes bug 13163.
diff --git a/changes/bug13163-stop-AlternateAuthorities-always-using-default-authorities b/changes/bug13163-stop-AlternateAuthorities-always-using-default-authorities
new file mode 100644
index 0000000000..eeaca926a2
--- /dev/null
+++ b/changes/bug13163-stop-AlternateAuthorities-always-using-default-authorities
@@ -0,0 +1,4 @@
+ o Minor bugfixes:
+ - Stop using the default authorities in networks which provide both
+ AlternateDirAuthority and AlternateBridgeAuthority.
+ Partially fixes bug 13163.
diff --git a/changes/bug13196-systemd-writable-run-directory b/changes/bug13196-systemd-writable-run-directory
new file mode 100644
index 0000000000..737c354984
--- /dev/null
+++ b/changes/bug13196-systemd-writable-run-directory
@@ -0,0 +1,3 @@
+ o Distribution:
+ - systemd unit file: set up /var/run/tor as writable for the Tor service.
+ Patch by intrigeri; resolves ticket 13196.
diff --git a/changes/bug13205 b/changes/bug13205
new file mode 100644
index 0000000000..446ffcf47b
--- /dev/null
+++ b/changes/bug13205
@@ -0,0 +1,5 @@
+ o Minor bugfixes:
+ - Return an error when the second or later arguments of the
+ "setevents" controller command are invalid events. Previously we
+ would return success while silently skipping invalid events. Fixes
+ bug 13205; bugfix on 0.2.3.2-alpha. Reported by "fpxnns".
diff --git a/changes/bug13213 b/changes/bug13213
new file mode 100644
index 0000000000..6dae8b06a1
--- /dev/null
+++ b/changes/bug13213
@@ -0,0 +1,4 @@
+ o Minor bugfixes (Bridges):
+ - When DisableNetwork is set, do not launch pluggable transport
+ plugins, and if any are running already, terminate the existing
+ instances. Resolves ticket 13213.
diff --git a/changes/bug13228 b/changes/bug13228
new file mode 100644
index 0000000000..0de013cb51
--- /dev/null
+++ b/changes/bug13228
@@ -0,0 +1,5 @@
+ o Build fixes:
+ - Improve configure script error message to make it clear
+ that compilation has failed and that user has to either
+ add --disable-asciidoc argument or install asciidoc.
+ Resolves ticket 13228.
diff --git a/changes/bug13285-disable-curve25519-build-errors b/changes/bug13285-disable-curve25519-build-errors
new file mode 100644
index 0000000000..285b642d39
--- /dev/null
+++ b/changes/bug13285-disable-curve25519-build-errors
@@ -0,0 +1,3 @@
+ o Minor bugfixes:
+ - Stop test & bench build failures with --disable-curve25519.
+ Fixes bug 13285.
diff --git a/changes/bug13290-avoid-div-zero-circuitstatus-pareto b/changes/bug13290-avoid-div-zero-circuitstatus-pareto
new file mode 100644
index 0000000000..cb175a7292
--- /dev/null
+++ b/changes/bug13290-avoid-div-zero-circuitstatus-pareto
@@ -0,0 +1,5 @@
+ o Minor bugfixes:
+ - In circuit_build_times_calculate_timeout() in circuitstats.c, avoid
+ dividing by zero in the pareto calculations. This traps under
+ clang -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error.
+ Fixes bug 13290; bugfix on tor-0.2.2.2-alpha.
diff --git a/changes/bug13291-spawn-test-race-condition b/changes/bug13291-spawn-test-race-condition
new file mode 100644
index 0000000000..bedd799119
--- /dev/null
+++ b/changes/bug13291-spawn-test-race-condition
@@ -0,0 +1,4 @@
+ o Minor bugfixes:
+ - Stop spawn test failures due to a race condition between the SIGCHLD
+ handler updating the process status, and the test reading it.
+ Fixes bug 13291; bugfix on 0.2.3.3-alpha.
diff --git a/changes/bug13314 b/changes/bug13314
new file mode 100644
index 0000000000..e9017fa3a0
--- /dev/null
+++ b/changes/bug13314
@@ -0,0 +1,4 @@
+ o Bugfixes:
+ - Handle malformed SOCKS5 requests properly by responding with an
+ appropriate error message before closing a TCP connection to the
+ user. Fixes bug 13314.
diff --git a/changes/bug13325 b/changes/bug13325
new file mode 100644
index 0000000000..b1da4d0bd5
--- /dev/null
+++ b/changes/bug13325
@@ -0,0 +1,4 @@
+ o Compilation fixes:
+ - Build and run correctly on systems like OpenBSD-current that
+ have patched OpenSSL to remove get_cipher_by_char and/or its
+ implementations. Fixes issue 13325.
diff --git a/changes/bug13331-make-j2-test-network-hang b/changes/bug13331-make-j2-test-network-hang
new file mode 100644
index 0000000000..85c0ad8e37
--- /dev/null
+++ b/changes/bug13331-make-j2-test-network-hang
@@ -0,0 +1,3 @@
+ o Minor bugfixes:
+ - Stop an apparent test-network hang when used with make -j2.
+ Fixes bug 13331.
diff --git a/changes/bug13393-format-time-interval-overflow-test b/changes/bug13393-format-time-interval-overflow-test
new file mode 100644
index 0000000000..cc15572000
--- /dev/null
+++ b/changes/bug13393-format-time-interval-overflow-test
@@ -0,0 +1,6 @@
+ o Minor bugfixes:
+ - Fix an instance of integer overflow in format_time_interval().
+ Fixes bug 13393.
+
+ o Minor features (test):
+ - Create unit tests for format_time_interval(). With bug 13393.
diff --git a/changes/bug13471 b/changes/bug13471
new file mode 100644
index 0000000000..c116a4aeeb
--- /dev/null
+++ b/changes/bug13471
@@ -0,0 +1,5 @@
+ o Major bugfixes (openssl bug workaround):
+ - Avoid crashing when using OpenSSL version 0.9.8zc, 1.0.0o, or
+ 1.0.1j, built with the 'no-ssl3' configuration option. Fixes
+ bug 13471. This is a workaround for an OpenSSL bug.
+
diff --git a/changes/bug13476-improve-time-handling b/changes/bug13476-improve-time-handling
new file mode 100644
index 0000000000..94ab95bf7c
--- /dev/null
+++ b/changes/bug13476-improve-time-handling
@@ -0,0 +1,20 @@
+ o Minor bugfixes:
+ - Set the correct day of year value when the system's localtime(_r)
+ or gmtime(_r) functions fail to set struct tm. Not externally visible.
+ Fixes bug 13476.
+ - Avoid unlikely signed integer overflow in tor_timegm on systems with
+ 32-bit time_t.
+ Fixes bug 13476.
+ o Minor enhancements (validation):
+ - Check all date/time values passed to tor_timegm and parse_rfc1123_time
+ for validity, taking leap years into account.
+ Improves HTTP header validation.
+ Implemented with bug 13476.
+ - Clamp year values returned by system localtime(_r) and gmtime(_r)
+ to year 1 in correct_tm. This ensures tor can read any values it
+ writes out.
+ Fixes bug 13476.
+ o Minor enhancements (testing):
+ - Add unit tests for tor_timegm signed overflow, tor_timegm and
+ parse_rfc1123_time validity checks, correct_tm year clamping.
+ Unit tests (visible) fixes in bug 13476.
diff --git a/changes/bug13477-memwipe-more-keys b/changes/bug13477-memwipe-more-keys
new file mode 100644
index 0000000000..cf8e0a9eb5
--- /dev/null
+++ b/changes/bug13477-memwipe-more-keys
@@ -0,0 +1,5 @@
+ o Minor bugfixes:
+ - Ensure we securely wipe keys from memory after
+ crypto_digest_get_digest and init_curve25519_keypair_from_file
+ have finished using them.
+ Fixes bug 13477.
diff --git a/changes/bug4244 b/changes/bug4244
new file mode 100644
index 0000000000..2b228ddacd
--- /dev/null
+++ b/changes/bug4244
@@ -0,0 +1,6 @@
+ o Minor bugfixes:
+ - Stop modifying the value of our DirReqStatistics torrc option just
+ because we're not a bridge or relay. This bug was causing Tor
+ Browser users to write "DirReqStatistics 0" in their torrc files
+ as if they had chosen to change the config. Fixes bug 4244; bugfix
+ on 0.2.3.1-alpha.
diff --git a/changes/bug7733a b/changes/bug7733a
new file mode 100644
index 0000000000..183c00994e
--- /dev/null
+++ b/changes/bug7733a
@@ -0,0 +1,4 @@
+ o Minor bugfixes:
+ - When a bridge has been configured without an identity digest
+ (not recommended), avoid launching an extra channel to it when
+ bootstrapping. Fixes bug 7733; bugfix on 0.2.4.4-alpha.
diff --git a/changes/bug8093 b/changes/bug8093
new file mode 100644
index 0000000000..f0fbc618c2
--- /dev/null
+++ b/changes/bug8093
@@ -0,0 +1,3 @@
+ o Downgraded warnings:
+ - Downgrade the severity of the 'unexpected sendme cell from client' from
+ 'warn' to 'protocol warning'. Closes ticket 8093.
diff --git a/changes/bug8197 b/changes/bug8197
new file mode 100644
index 0000000000..b8e467dc38
--- /dev/null
+++ b/changes/bug8197
@@ -0,0 +1,6 @@
+ o Minor refactoring:
+ - Reworking API of policies_parse_exit_policy() function to use a
+ bitmask to represent parsing options instead of a confusing mess
+ of booleans. Resolves ticket 8197.
+ - Introducing helper function to parse ExitPolicy in or_options_t
+ structure.
diff --git a/changes/bug8402 b/changes/bug8402
new file mode 100644
index 0000000000..96a3084ecf
--- /dev/null
+++ b/changes/bug8402
@@ -0,0 +1,5 @@
+ o Major features (bridges):
+ - Expose the outgoing upstream HTTP/SOCKS proxy to pluggable
+ transports if they are configured via the "TOR_PT_PROXY"
+ enviorment variable. Implements proposal 232. Resolves
+ ticket 8402.
diff --git a/changes/disable_sslv3 b/changes/disable_sslv3
new file mode 100644
index 0000000000..bb4c2df7a2
--- /dev/null
+++ b/changes/disable_sslv3
@@ -0,0 +1,4 @@
+ o Major security fixes:
+ - Disable support for SSLv3. All versions of OpenSSL in use with
+ Tor today support TLS 1.0 or later, so we can safely turn off
+ support for this old (and insecure) protocol. Fixes bug 13426.
diff --git a/changes/feature13153 b/changes/feature13153
new file mode 100644
index 0000000000..15f8fe8b4f
--- /dev/null
+++ b/changes/feature13153
@@ -0,0 +1,5 @@
+ o Code simplication:
+ - Clients are now willing to send optimistic circuit data (before they
+ receive a 'connected' cell) to relays of any version. We used to
+ only do it for relays running 0.2.3.1-alpha or later, but now all
+ relays are new enough. Resolves ticket 13153.
diff --git a/changes/feature13161-TestingDirAuthVoteExit b/changes/feature13161-TestingDirAuthVoteExit
new file mode 100644
index 0000000000..d6c8f414a3
--- /dev/null
+++ b/changes/feature13161-TestingDirAuthVoteExit
@@ -0,0 +1,7 @@
+ o Minor features (testing):
+ - Add the TestingDirAuthVoteExit option, a list of nodes to vote
+ Exit for regardless of their uptime, bandwidth, or exit policy.
+ TestingTorNetwork must be set for this option to have any effect.
+ Works around an issue where authorities would take up to 35 minutes
+ to give nodes the Exit flag in a test network, despite short
+ consensus intervals. Partially implements ticket 13161.
diff --git a/changes/feature13161-test-network-delay-option b/changes/feature13161-test-network-delay-option
new file mode 100644
index 0000000000..1cf2e71a37
--- /dev/null
+++ b/changes/feature13161-test-network-delay-option
@@ -0,0 +1,4 @@
+ o Minor features (testing):
+ - Add a --delay option to test-network.sh, which configures the delay
+ before the chutney network tests for data transmission.
+ Partially implements ticket 13161.
diff --git a/changes/feature13211 b/changes/feature13211
new file mode 100644
index 0000000000..dcb01966c8
--- /dev/null
+++ b/changes/feature13211
@@ -0,0 +1,6 @@
+ o Major features (performance):
+ - Allow clients to use optimistic data when connecting to a hidden
+ service, which should cut out the initial round-trip for client-side
+ programs including Tor Browser. (Now that Tor 0.2.2.x is obsolete,
+ all hidden services should support server-side optimistic
+ data.) See proposal 181 for details. Implements ticket 13211.
diff --git a/changes/issue13163-improve-DIRINFO-flags-comments b/changes/issue13163-improve-DIRINFO-flags-comments
new file mode 100644
index 0000000000..3acb1f3caf
--- /dev/null
+++ b/changes/issue13163-improve-DIRINFO-flags-comments
@@ -0,0 +1,5 @@
+ o Minor refactoring:
+ - Document usage of the NO_DIRINFO and ALL_DIRINFO flags clearly in
+ functions which take them as arguments. Replace 0 with NO_DIRINFO
+ in a function call for clarity.
+ Seeks to prevent future issues like 13163.
diff --git a/changes/issue13284-spurious-clang-shallow-analyze-errors b/changes/issue13284-spurious-clang-shallow-analyze-errors
new file mode 100644
index 0000000000..c08fa1f1b0
--- /dev/null
+++ b/changes/issue13284-spurious-clang-shallow-analyze-errors
@@ -0,0 +1,3 @@
+ o Minor bugfixes:
+ - Avoid 4 null pointer errors under clang shallow analysis by using
+ tor_assert() to prove that the pointers aren't null. Fixes bug 13284.
diff --git a/changes/require-c99 b/changes/require-c99
new file mode 100644
index 0000000000..61d961273a
--- /dev/null
+++ b/changes/require-c99
@@ -0,0 +1,10 @@
+ o New compiler requirements:
+ - Tor 0.2.6.x requires that your compiler support more of the C99
+ language standard than before. The 'configure' script now detects
+ whether your compiler supports C99 mid-block declarations and
+ designated initializers. If it does not, Tor will not compile.
+
+ We may revisit this requirement if it turns out that a significant
+ number of people need to build Tor with compilers that don't
+ bother implementing a 15-year-old standard. Closes ticket 13233.
+
diff --git a/changes/ticket11144 b/changes/ticket11144
new file mode 100644
index 0000000000..265481b964
--- /dev/null
+++ b/changes/ticket11144
@@ -0,0 +1,8 @@
+ o New features (sample torrc):
+ - Add a new, infrequently-changed "torrc.minimal". This file's
+ purpose is similar to torrc.sample, but it is meant to be small
+ and change as infrequently as possible, for the benefit of
+ users whose systems prompt them for intervention whenever a
+ default configuration file is changed. Making this change
+ allows us to update torrc.sample to be a more generally useful
+ "sample torrc".
diff --git a/changes/ticket11243 b/changes/ticket11243
new file mode 100644
index 0000000000..0b470baf79
--- /dev/null
+++ b/changes/ticket11243
@@ -0,0 +1,7 @@
+ o Major features (downloading):
+ - Upon receiving a server descriptor, microdescriptor, extrainfo
+ document, or other object that is unparseable, if its digest
+ matches what we expected, then mark it as not to be downloaded
+ again. Previously, when we got a descriptor we didn't like, we
+ would keep trying to download it over and over. Closes ticket
+ 11243.
diff --git a/changes/ticket11582 b/changes/ticket11582
new file mode 100644
index 0000000000..e54f77998e
--- /dev/null
+++ b/changes/ticket11582
@@ -0,0 +1,5 @@
+ o Minor features:
+ - Re-check our address after we detect a changed IP address from
+ getsockname(). This ensures that the controller command "GETINFO
+ address" will report the correct value. Resolves ticket 11582.
+ Patch from "ra". \ No newline at end of file
diff --git a/changes/ticket12884 b/changes/ticket12884
new file mode 100644
index 0000000000..cd7e87c085
--- /dev/null
+++ b/changes/ticket12884
@@ -0,0 +1,3 @@
+ o Removed code:
+ - We no longer remind the user about obsolete configuration options
+ that have been obsolete since 0.2.3.x or later. Patch by Adrien Bak.
diff --git a/changes/ticket961 b/changes/ticket961
new file mode 100644
index 0000000000..018f26554d
--- /dev/null
+++ b/changes/ticket961
@@ -0,0 +1,5 @@
+ o Minor features:
+ - A new AccountingRule option lets you set whether you'd like the
+ AccountingMax value to be applied separately to inbound and
+ outbound traffic, or applied to the sum of inbound and outbound
+ traffic. Resolves ticket 961. Patch by "chobe".
diff --git a/changes/ticket_13119 b/changes/ticket_13119
new file mode 100644
index 0000000000..042106eeab
--- /dev/null
+++ b/changes/ticket_13119
@@ -0,0 +1,6 @@
+ o Code refactoring:
+ - Revise all unit tests that used the legacy test_* macros to
+ instead use the recommended tt_* macros. This patch was
+ generated with coccinelle, to avoid manual errors. Closes
+ ticket 13119.
+
diff --git a/configure.ac b/configure.ac
index 414c72a42c..4c7da5d76a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -153,6 +153,9 @@ AC_ARG_ENABLE(tool-name-check,
AC_ARG_ENABLE(seccomp,
AS_HELP_STRING(--disable-seccomp, do not attempt to use libseccomp))
+AC_ARG_ENABLE(libscrypt,
+ AS_HELP_STRING(--disable-libscrypt, do not attempt to use libscrypt))
+
dnl check for the correct "ar" when cross-compiling
AN_MAKEVAR([AR], [AC_PROG_AR])
AN_PROGRAM([ar], [AC_PROG_AR])
@@ -191,6 +194,7 @@ AM_CONDITIONAL(USE_FW_HELPER, test x$natpmp = xtrue || test x$upnp = xtrue)
AM_CONDITIONAL(NAT_PMP, test x$natpmp = xtrue)
AM_CONDITIONAL(MINIUPNPC, test x$upnp = xtrue)
AM_PROG_CC_C_O
+AC_PROG_CC_C99
AC_ARG_VAR(PYTHON)
AC_CHECK_PROGS(PYTHON, [python python2 python2.7 python3 python3.3])
@@ -221,6 +225,28 @@ AC_C_FLEXIBLE_ARRAY_MEMBER
fi
])
+AC_CACHE_CHECK([for working C99 mid-block declaration syntax],
+ tor_cv_c_c99_decl,
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([], [int x; x = 3; int y; y = 4 + x;])],
+ [tor_cv_c_c99_decl=yes],
+ [tor_cv_c_c99_decl=no] )])
+if test "$tor_cv_c_c99_decl" != "yes"; then
+ AC_MSG_ERROR([Your compiler doesn't support c99 mid-block declarations. This is required as of Tor 0.2.6.x])
+fi
+
+AC_CACHE_CHECK([for working C99 designated initializers],
+ tor_cv_c_c99_designated_init,
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([struct s { int a; int b; };],
+ [[ struct s ss = { .b = 5, .a = 6 }; ]])],
+ [tor_cv_c_c99_designated_init=yes],
+ [tor_cv_c_c99_designated_init=no] )])
+
+if test "$tor_cv_c_c99_designated_init" != "yes"; then
+ AC_MSG_ERROR([Your compiler doesn't support c99 designated initializers. This is required as of Tor 0.2.6.x])
+fi
+
AC_PATH_PROG([SHA1SUM], [sha1sum], none)
AC_PATH_PROG([OPENSSL], [openssl], none)
@@ -339,6 +365,7 @@ AC_CHECK_FUNCS(
socketpair \
strlcat \
strlcpy \
+ strnlen \
strptime \
strtok_r \
strtoull \
@@ -556,6 +583,10 @@ else
fi
AC_SUBST(TOR_OPENSSL_LIBS)
+AC_CHECK_MEMBERS([struct ssl_method_st.get_cipher_by_char], , ,
+[#include <openssl/ssl.h>
+])
+
dnl ------------------------------------------------------
dnl Where do you live, zlib? And how do we call you?
@@ -604,11 +635,12 @@ if test x$enable_gcc_hardening != xno; then
TOR_CHECK_CFLAGS(-fstack-protector-all, also_link)
AS_VAR_PUSHDEF([can_compile], [tor_cv_cflags_-fstack-protector-all])
AS_VAR_PUSHDEF([can_link], [tor_can_link_-fstack-protector-all])
+m4_ifdef([AS_VAR_IF],[
AS_VAR_IF(can_compile, [yes],
AS_VAR_IF(can_link, [yes],
[],
AC_MSG_ERROR([We tried to build with stack protection; it looks like your compiler supports it but your libc does not provide it. Are you missing libssp? (You can --disable-gcc-hardening to ignore this error.)]))
- )
+ )])
AS_VAR_POPDEF([can_link])
AS_VAR_POPDEF([can_compile])
TOR_CHECK_CFLAGS(-Wstack-protector)
@@ -722,6 +754,14 @@ if test "x$enable_seccomp" != "xno"; then
fi
dnl ============================================================
+dnl Check for libscrypt
+
+if test "x$enable_libscrypt" != "xno"; then
+ AC_CHECK_HEADERS([libscrypt.h])
+ AC_SEARCH_LIBS(libscrypt_scrypt, [scrypt])
+fi
+
+dnl ============================================================
dnl We need an implementation of curve25519.
dnl set these defaults.
@@ -1499,7 +1539,7 @@ if test x$enable_gcc_warnings = xyes || test x$enable_gcc_warnings_advisory = xy
if test x$have_gcc4 = xyes ; then
# These warnings break gcc 3.3.5 and work on gcc 4.0.2
- CFLAGS="$CFLAGS -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement -Wold-style-definition"
+ CFLAGS="$CFLAGS -Winit-self -Wmissing-field-initializers -Wold-style-definition"
fi
if test x$have_gcc42 = xyes ; then
@@ -1555,6 +1595,7 @@ AC_CONFIG_FILES([
contrib/dist/torctl
contrib/dist/tor.service
src/config/torrc.sample
+ src/config/torrc.minimal
])
if test x$asciidoc = xtrue && test "$ASCIIDOC" = "none" ; then
@@ -1563,7 +1604,9 @@ if test x$asciidoc = xtrue && test "$ASCIIDOC" = "none" ; then
if ! [[ -f "$srcdir/$file.1.in" ]] || ! [[ -f "$srcdir/$file.html.in" ]] ; then
echo "==================================";
echo;
- echo "You need asciidoc installed to be able to build the manpage.";
+ echo "Building Tor has failed since manpages cannot be built.";
+ echo;
+ echo "You need asciidoc installed to be able to build the manpages.";
echo "To build without manpages, use the --disable-asciidoc argument";
echo "when calling configure.";
echo;
diff --git a/contrib/dist/tor.service.in b/contrib/dist/tor.service.in
index 20ceecf0ca..57409a7b0a 100644
--- a/contrib/dist/tor.service.in
+++ b/contrib/dist/tor.service.in
@@ -22,6 +22,7 @@ InaccessibleDirectories = /home
ReadOnlyDirectories = /
ReadWriteDirectories = @LOCALSTATEDIR@/lib/tor
ReadWriteDirectories = @LOCALSTATEDIR@/log/tor
+ReadWriteDirectories = @LOCALSTATEDIR@/run/tor
NoNewPrivileges = yes
[Install]
diff --git a/doc/HACKING b/doc/HACKING
index 6b21426497..5c71b74bd1 100644
--- a/doc/HACKING
+++ b/doc/HACKING
@@ -134,6 +134,27 @@ output directory, use `make coverage-html HTML_COVER_DIR=./funky_new_cov_dir`.
Coverage diffs using lcov are not currently implemented, but are being
investigated (as of July 2014).
+Running the unit tests
+~~~~~~~~~~~~~~~~~~~~~~
+
+To quickly run all tests:
+-----
+ make check
+-----
+
+To run unit tests only:
+-----
+ make test
+-----
+
+To selectively run just some tests (the following can be combined
+arbitrarily):
+-----
+ ./src/test/test <name_of_test> [<name of test 2>] ...
+ ./src/test/test <prefix_of_name_of_test>.. [<prefix_of_name_of_test2>..] ...
+ ./src/test/test :<name_of_excluded_test> [:<name_of_excluded_test2]...
+-----
+
Running gcov for unit test coverage
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -512,7 +533,7 @@ interesting and understandable.
2.6) Clean everything one last time.
- 2.7) Run it through fmt to make it pretty.
+ 2.7) Run ./scripts/maint/format_changelog.py to make it prettier.
3) Compose a short release blurb to highlight the user-facing
changes. Insert said release blurb into the ChangeLog stanza. If it's
@@ -534,10 +555,12 @@ in their approved versions list.
git tag -u <keyid> tor-0.2.x.y-status
git push origin tag tor-0.2.x.y-status
-8) scp the tarball and its sig to the website in the dist/ directory
-(i.e. /srv/www-master.torproject.org/htdocs/dist/ on vescum). Edit
-"include/versions.wmi" and "Makefile" to note the new version. From your
-website checkout, run ./publish to build and publish the website.
+8a) scp the tarball and its sig to the dist website, i.e.
+/srv/dist-master.torproject.org/htdocs/ on dist-master. When you want
+it to go live, you run "static-update-component dist.torproject.org"
+on dist-master.
+
+8b) Edit "include/versions.wmi" and "Makefile" to note the new version.
9) Email the packagers (cc'ing tor-assistants) that a new tarball is up.
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index d6b14329d1..f625c45161 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -72,7 +72,7 @@ COMMAND-LINE OPTIONS
[[opt-serviceinstall]] **--service install** [**--options** __command-line options__]::
Install an instance of Tor as a Windows service, with the provided
command-line options. Current instructions can be found at
- https://trac.torproject.org/projects/tor/wiki/doc/TorFAQ#HowdoIrunmyTorrelayasanNTservice
+ https://www.torproject.org/docs/faq#NTService
[[opt-service]] **--service** **remove**|**start**|**stop**::
Remove, start, or stop a configured Tor Windows service.
@@ -964,10 +964,10 @@ The following options are useful only for clients (that is, if
(SOCKS 4, SOCKS 5, TransPort connections, NATDPort connections,
and DNSPort requests are all considered to be different protocols.)
**IsolateDestPort**;;
- Don't share circuits with streams targetting a different
+ Don't share circuits with streams targeting a different
destination port.
**IsolateDestAddr**;;
- Don't share circuits with streams targetting a different
+ Don't share circuits with streams targeting a different
destination address.
**SessionGroup=**__INT__;;
If no other isolation rules would prevent it, allow streams
@@ -1018,7 +1018,7 @@ The following options are useful only for clients (that is, if
requests via this connection.
**PreferIPv6Automap**;;
When serving a hostname lookup request on this port that
- should get automapped (according to AutomapHostsOnResove),
+ should get automapped (according to AutomapHostsOnResolve),
if we could return either an IPv4 or an IPv6 answer, prefer
an IPv6 answer. (On by default.)
**PreferSOCKSNoAuth**;;
@@ -1425,7 +1425,7 @@ The following options are useful only for clients (that is, if
whose view of the current time is skewed. If this option is set to 0, we
do not send this timestamp, and hidden services on obsolete Tor versions
will not work. If this option is set to 1, we send the timestamp. If
- this optoin is "auto", we take a recommendation from the latest consensus
+ this option is "auto", we take a recommendation from the latest consensus
document. (Default: auto)
@@ -1635,19 +1635,31 @@ is non-zero):
to 0 will disable the heartbeat. (Default: 6 hours)
[[AccountingMax]] **AccountingMax** __N__ **bytes**|**KBytes**|**MBytes**|**GBytes**|**KBits**|**MBits**|**GBits**|**TBytes**::
- Never send more than the specified number of bytes in a given accounting
- period, or receive more than that number in the period. For example, with
- AccountingMax set to 1 GByte, a server could send 900 MBytes and
- receive 800 MBytes and continue running. It will only hibernate once
- one of the two reaches 1 GByte. When the number of bytes gets low,
- Tor will stop accepting new connections and circuits. When the
- number of bytes is exhausted, Tor will hibernate until some
- time in the next accounting period. To prevent all servers from waking at
- the same time, Tor will also wait until a random point in each period
- before waking up. If you have bandwidth cost issues, enabling hibernation
- is preferable to setting a low bandwidth, since it provides users with a
- collection of fast servers that are up some of the time, which is more
- useful than a set of slow servers that are always "available".
+ Limits the max number of bytes sent and received within a set time period
+ using a given calculation rule (see: AccountingStart, AccountingRule).
+ Useful if you need to stay under a specific bandwidth. By default, the
+ number used for calculation is the max of either the bytes sent or
+ received. For example, with AccountingMax set to 1 GByte, a server
+ could send 900 MBytes and receive 800 MBytes and continue running.
+ It will only hibernate once one of the two reaches 1 GByte. This can
+ be changed to use the sum of the both bytes received and sent by setting
+ the AccountingRule option to "sum" (total bandwidth in/out). When the
+ number of bytes remaining gets low, Tor will stop accepting new connections
+ and circuits. When the number of bytes is exhausted, Tor will hibernate
+ until some time in the next accounting period. To prevent all servers
+ from waking at the same time, Tor will also wait until a random point
+ in each period before waking up. If you have bandwidth cost issues,
+ enabling hibernation is preferable to setting a low bandwidth, since
+ it provides users with a collection of fast servers that are up some
+ of the time, which is more useful than a set of slow servers that are
+ always "available".
+
+[[AccountingRule]] **AccountingRule** **sum**|**max**::
+ How we determine when our AccountingMax has been reached (when we
+ should hibernate) during a time interval. Set to "max" to calculate
+ using the higher of either the sent or received bytes (this is the
+ default functionality). Set to "sum" to calculate using the sent
+ plus received bytes. (Default: max)
[[AccountingStart]] **AccountingStart** **day**|**week**|**month** [__day__] __HH:MM__::
Specify how long accounting periods last. If **month** is given, each
@@ -2020,7 +2032,7 @@ The following options are used to configure a hidden service.
[[HiddenServicePort]] **HiddenServicePort** __VIRTPORT__ [__TARGET__]::
Configure a virtual port VIRTPORT for a hidden service. You may use this
option multiple times; each time applies to the service using the most
- recent hiddenservicedir. By default, this option maps the virtual port to
+ recent HiddenServiceDir. By default, this option maps the virtual port to
the same port on 127.0.0.1 over TCP. You may override the target port,
address, or both by specifying a target of addr, port, or addr:port.
You may also have multiple lines with the same VIRTPORT: when a user
@@ -2185,6 +2197,15 @@ The following options are used for running a testing Tor network.
Try this often to download a v3 authority certificate before giving up.
Changing this requires that **TestingTorNetwork** is set. (Default: 8)
+[[TestingDirAuthVoteExit]] **TestingDirAuthVoteExit** __node__,__node__,__...__::
+ A list of identity fingerprints, nicknames, country codes and
+ address patterns of nodes to vote Exit for regardless of their
+ uptime, bandwidth, or exit policy. See the **ExcludeNodes**
+ option for more information on how to specify nodes.
+ +
+ In order for this option to have any effect, **TestingTorNetwork**
+ has to be set.
+
[[TestingDirAuthVoteGuard]] **TestingDirAuthVoteGuard** __node__,__node__,__...__::
A list of identity fingerprints, nicknames, country codes and
address patterns of nodes to vote Guard for regardless of their
diff --git a/scripts/coccinelle/malloc_cast.cocci b/scripts/coccinelle/malloc_cast.cocci
new file mode 100644
index 0000000000..20321d4fd0
--- /dev/null
+++ b/scripts/coccinelle/malloc_cast.cocci
@@ -0,0 +1,38 @@
+@cast_malloc@
+expression e;
+type T;
+@@
+- (T *)tor_malloc(e)
++ tor_malloc(e)
+
+@cast_malloc_zero@
+expression e;
+type T;
+identifier func;
+@@
+- (T *)tor_malloc_zero(e)
++ tor_malloc_zero(e)
+
+@cast_calloc@
+expression a, b;
+type T;
+identifier func;
+@@
+- (T *)tor_calloc(a, b)
++ tor_calloc(a, b)
+
+@cast_realloc@
+expression e;
+expression p;
+type T;
+@@
+- (T *)tor_realloc(p, e)
++ tor_realloc(p, e)
+
+@cast_reallocarray@
+expression a,b;
+expression p;
+type T;
+@@
+- (T *)tor_reallocarray(p, a, b)
++ tor_reallocarray(p, a, b)
diff --git a/scripts/coccinelle/uncalloc.cocci b/scripts/coccinelle/uncalloc.cocci
new file mode 100644
index 0000000000..bf3f74165a
--- /dev/null
+++ b/scripts/coccinelle/uncalloc.cocci
@@ -0,0 +1,13 @@
+
+@@
+expression a;
+@@
+- tor_calloc(1, a)
++ tor_malloc_zero(a)
+
+@@
+expression a;
+@@
+- tor_calloc(a, 1)
++ tor_malloc_zero(a)
+
diff --git a/scripts/codegen/makedesc.py b/scripts/codegen/makedesc.py
new file mode 100644
index 0000000000..e0b2aed3f4
--- /dev/null
+++ b/scripts/codegen/makedesc.py
@@ -0,0 +1,218 @@
+#!/usr/bin/python
+# Copyright 2014, The Tor Project, Inc.
+# See LICENSE for license information
+
+# This is a kludgey python script that uses ctypes and openssl to sign
+# router descriptors and extrainfo documents and put all the keys in
+# the right places. There are examples at the end of the file.
+
+# I've used this to make inputs for unit tests. I wouldn't suggest
+# using it for anything else.
+
+import base64
+import binascii
+import ctypes
+import ctypes.util
+import hashlib
+
+crypt = ctypes.CDLL(ctypes.util.find_library('crypto'))
+BIO_s_mem = crypt.BIO_s_mem
+BIO_s_mem.argtypes = []
+BIO_s_mem.restype = ctypes.c_void_p
+
+BIO_new = crypt.BIO_new
+BIO_new.argtypes = [ctypes.c_void_p]
+BIO_new.restype = ctypes.c_void_p
+
+RSA_generate_key = crypt.RSA_generate_key
+RSA_generate_key.argtypes = [ctypes.c_int, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_void_p]
+RSA_generate_key.restype = ctypes.c_void_p
+
+RSA_private_encrypt = crypt.RSA_private_encrypt
+RSA_private_encrypt.argtypes = [
+ ctypes.c_int, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int ]
+RSA_private_encrypt.restype = ctypes.c_int
+
+i2d_RSAPublicKey = crypt.i2d_RSAPublicKey
+i2d_RSAPublicKey.argtypes = [
+ ctypes.c_void_p, ctypes.POINTER(ctypes.c_char_p)
+]
+i2d_RSAPublicKey.restype = ctypes.c_int
+
+def b64(x):
+ x = base64.b64encode(x)
+ res = []
+ for i in xrange(0, len(x), 64):
+ res.append(x[i:i+64]+"\n")
+ return "".join(res)
+
+def bio_extract(bio):
+ buf = ctypes.c_char_p()
+ length = crypt.BIO_ctrl(bio, 3, 0, ctypes.byref(buf))
+ return ctypes.string_at(buf, length)
+
+def make_key(e=65537):
+ rsa = crypt.RSA_generate_key(1024, e, None, None)
+ bio = BIO_new(BIO_s_mem())
+ crypt.PEM_write_bio_RSAPublicKey(bio, rsa)
+ pem = bio_extract(bio).rstrip()
+ crypt.BIO_free(bio)
+
+ buf = ctypes.create_string_buffer(1024)
+ pBuf = ctypes.c_char_p(ctypes.addressof(buf))
+ n = crypt.i2d_RSAPublicKey(rsa, ctypes.byref(pBuf))
+ s = buf.raw[:n]
+ digest = hashlib.sha1(s).digest()
+
+ return (rsa,pem,digest)
+
+def signdesc(body, args_out=None):
+ rsa, ident_pem, id_digest = make_key()
+ _, onion_pem, _ = make_key()
+
+ hexdigest = binascii.b2a_hex(id_digest).upper()
+ fingerprint = " ".join(hexdigest[i:i+4] for i in range(0,len(hexdigest),4))
+
+ MAGIC = "<<<<<<MAGIC>>>>>>"
+ args = {
+ "RSA-IDENTITY" : ident_pem,
+ "ONION-KEY" : onion_pem,
+ "FINGERPRINT" : fingerprint,
+ "FINGERPRINT-NOSPACE" : hexdigest,
+ "RSA-SIGNATURE" : MAGIC
+ }
+ if args_out:
+ args_out.update(args)
+ body = body.format(**args)
+
+ idx = body.rindex("\nrouter-signature")
+ end_of_sig = body.index("\n", idx+1)
+
+ signed_part = body[:end_of_sig+1]
+
+ digest = hashlib.sha1(signed_part).digest()
+ assert len(digest) == 20
+
+ buf = ctypes.create_string_buffer(1024)
+ n = RSA_private_encrypt(20, digest, buf, rsa, 1)
+ sig = buf.raw[:n]
+
+ sig = """-----BEGIN SIGNATURE-----
+%s
+-----END SIGNATURE-----""" % b64(sig).rstrip()
+ body = body.replace(MAGIC, sig)
+
+ return body.rstrip()
+
+def emit_ri(name, body, args_out=None):
+ print "const char %s[] ="%name
+ body = "\n".join(line.rstrip() for line in body.split("\n"))+"\n"
+ b = signdesc(body, args_out)
+ for line in b.split("\n"):
+ print ' "%s\\n"'%line
+ print " ;"
+
+def emit_ei(name, body):
+ args = { 'NAME' : name }
+ emit_ri(name, body, args)
+ args['key'] = "\n".join(
+ ' "%s\\n"'%line for line in args['RSA-IDENTITY'].split("\n"))
+ print """
+const char {NAME}_fp[] = "{FINGERPRINT-NOSPACE}";
+const char {NAME}_key[] =
+{key};""".format(**args)
+
+if 0:
+ emit_ri("minimal",
+ """\
+router fred 127.0.0.1 9001 0 9002
+signing-key
+{RSA-IDENTITY}
+onion-key
+{ONION-KEY}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+reject *:*
+router-signature
+{RSA-SIGNATURE}
+""")
+
+if 0:
+ emit_ri("maximal",
+ """\
+router fred 127.0.0.1 9001 0 9002
+signing-key
+{RSA-IDENTITY}
+onion-key
+{ONION-KEY}
+published 2014-10-05 12:00:00
+bandwidth 1000 1000 1000
+reject 127.0.0.1:*
+accept *:80
+reject *:*
+ipv6-policy accept 80,100,101
+ntor-onion-key s7rSohmz9SXn8WWh1EefTHIsWePthsEntQi0WL+ScVw
+uptime 1000
+hibernating 0
+unrecognized-keywords are just dandy in this format
+platform Tor 0.2.4.23 on a Banana PC Jr 6000 Series
+contact O.W.Jones
+fingerprint {FINGERPRINT}
+read-history 900 1,2,3,4
+write-history 900 1,2,3,4
+extra-info-digest AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+hidden-service-dir
+allow-single-hop-exits
+family $AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA $BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+caches-extra-info
+or-address [::1:2:3:4]:9999
+or-address 127.0.0.99:10000
+opt fred is a fine router
+router-signature
+{RSA-SIGNATURE}
+""")
+
+if 0:
+ emit_ei("maximal",
+"""\
+extra-info bob {FINGERPRINT-NOSPACE}
+published 2014-10-05 20:07:00
+opt foobarbaz
+read-history 900 1,2,3
+write-history 900 1,2,3
+dirreq-v2-ips 1
+dirreq-v3-ips 100
+dirreq-v3-reqs blahblah
+dirreq-v2-share blahblah
+dirreq-v3-share blahblah
+dirreq-v2-resp djfkdj
+dirreq-v3-resp djfkdj
+dirreq-v2-direct-dl djfkdj
+dirreq-v3-direct-dl djfkdj
+dirreq-v2-tunneled-dl djfkdj
+dirreq-v3-tunneled-dl djfkdj
+dirreq-stats-end foobar
+entry-ips jfsdfds
+entry-stats-end ksdflkjfdkf
+cell-stats-end FOO
+cell-processed-cells FOO
+cell-queued-cells FOO
+cell-time-in-queue FOO
+cell-circuits-per-decile FOO
+exit-stats-end FOO
+exit-kibibytes-written FOO
+exit-kibibytes-read FOO
+exit-streams-opened FOO
+router-signature
+{RSA-SIGNATURE}
+""")
+
+if 0:
+ emit_ei("minimal",
+"""\
+extra-info bob {FINGERPRINT-NOSPACE}
+published 2014-10-05 20:07:00
+router-signature
+{RSA-SIGNATURE}
+""")
+
diff --git a/scripts/codegen/run_trunnel.sh b/scripts/codegen/run_trunnel.sh
new file mode 100755
index 0000000000..5f694ce6c9
--- /dev/null
+++ b/scripts/codegen/run_trunnel.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+if test "x$TRUNNEL_PATH" != "x"; then
+ PYTHONPATH="${TRUNNEL_PATH}:${PYTHONPATH}"
+ export PYTHONPATH
+fi
+
+python -m trunnel --require-version=1.2 ./src/trunnel/*.trunnel
+
+python -m trunnel --require-version=1.2 --write-c-files --target-dir=./src/ext/trunnel/
+
diff --git a/scripts/maint/format_changelog.py b/scripts/maint/format_changelog.py
index f67e89b602..b1a0988766 100755
--- a/scripts/maint/format_changelog.py
+++ b/scripts/maint/format_changelog.py
@@ -12,6 +12,7 @@
import os
import re
import sys
+import optparse
# ==============================
# Oh, look! It's a cruddy approximation to Knuth's elegant text wrapping
@@ -33,6 +34,9 @@ import sys
NO_HYPHENATE=set("""
pf-divert
+tor-resolve
+tor-gencert
+tor-fw-helper
""".split())
LASTLINE_UNDERFLOW_EXPONENT = 1
@@ -115,7 +119,10 @@ def wrap_graf(words, prefix_len1=0, prefix_len2=0, width=72):
return lines
-def hyphenateable(word):
+def hyphenatable(word):
+ if "--" in word:
+ return False
+
if re.match(r'^[^\d\-]\D*-', word):
stripped = re.sub(r'^\W+','',word)
stripped = re.sub(r'\W+$','',word)
@@ -128,7 +135,7 @@ def split_paragraph(s):
r = []
for word in s.split():
- if hyphenateable(word):
+ if hyphenatable(word):
while "-" in word:
a,word = word.split("-",1)
r.append(a+"\xff")
@@ -156,10 +163,13 @@ TP_SECHEAD = 3
TP_ITEMFIRST = 4
TP_ITEMBODY = 5
TP_END = 6
+TP_PREHEAD = 7
def head_parser(line):
- if re.match(r'^[A-Z]', line):
+ if re.match(r'^Changes in', line):
return TP_MAINHEAD
+ elif re.match(r'^[A-Za-z]', line):
+ return TP_PREHEAD
elif re.match(r'^ o ', line):
return TP_SECHEAD
elif re.match(r'^\s*$', line):
@@ -178,17 +188,62 @@ def body_parser(line):
return TP_BLANK
elif re.match(r'^Changes in', line):
return TP_END
+ elif re.match(r'^\s+\S', line):
+ return TP_HEADTEXT
else:
print "Weird line %r"%line
+def clean_head(head):
+ return head
+
+def head_score(s):
+ m = re.match(r'^ +o (.*)', s)
+ if not m:
+ print >>sys.stderr, "Can't score %r"%s
+ return 99999
+ lw = m.group(1).lower()
+ if lw.startswith("security") and "feature" not in lw:
+ score = -300
+ elif lw.startswith("deprecated versions"):
+ score = -200
+ elif "build require" in lw:
+ score = -100
+ elif lw.startswith("major feature"):
+ score = 00
+ elif lw.startswith("major bug"):
+ score = 50
+ elif lw.startswith("major"):
+ score = 70
+ elif lw.startswith("minor feature"):
+ score = 200
+ elif lw.startswith("minor bug"):
+ score = 250
+ elif lw.startswith("minor"):
+ score = 270
+ else:
+ score = 1000
+
+ if 'secur' in lw:
+ score -= 2
+
+ if "(other)" in lw:
+ score += 2
+
+ if '(' not in lw:
+ score -= 1
+
+ return score
+
class ChangeLog(object):
- def __init__(self):
+ def __init__(self, wrapText=True):
+ self.prehead = []
self.mainhead = None
self.headtext = []
self.curgraf = None
self.sections = []
self.cursection = None
self.lineno = 0
+ self.wrapText = wrapText
def addLine(self, tp, line):
self.lineno += 1
@@ -197,6 +252,9 @@ class ChangeLog(object):
assert not self.mainhead
self.mainhead = line
+ elif tp == TP_PREHEAD:
+ self.prehead.append(line)
+
elif tp == TP_HEADTEXT:
if self.curgraf is None:
self.curgraf = []
@@ -240,6 +298,11 @@ class ChangeLog(object):
self.lint_item(item_line, grafs, head_type)
def dumpGraf(self,par,indent1,indent2=-1):
+ if not self.wrapText:
+ for line in par:
+ print line
+ return
+
if indent2 == -1:
indent2 = indent1
text = " ".join(re.sub(r'\s+', ' ', line.strip()) for line in par)
@@ -249,7 +312,26 @@ class ChangeLog(object):
initial_indent=" "*indent1,
subsequent_indent=" "*indent2))
+ def collateAndSortSections(self):
+ heads = []
+ sectionsByHead = { }
+ for _, head, items in self.sections:
+ head = clean_head(head)
+ try:
+ s = sectionsByHead[head]
+ except KeyError:
+ s = sectionsByHead[head] = []
+ heads.append( (head_score(head), head.lower(), head, s) )
+
+ s.extend(items)
+
+ heads.sort()
+ self.sections = [ (0, head, items) for _1,_2,head,items in heads ]
+
def dump(self):
+ if self.prehead:
+ self.dumpGraf(self.prehead, 0)
+ print
print self.mainhead
for par in self.headtext:
self.dumpGraf(par, 2)
@@ -267,20 +349,36 @@ class ChangeLog(object):
print
print
-CL = ChangeLog()
-parser = head_parser
-
-if len(sys.argv) == 1:
+op = optparse.OptionParser(usage="usage: %prog [options] [filename]")
+op.add_option('-W', '--no-wrap', action='store_false',
+ dest='wrapText', default=True,
+ help='Do not re-wrap paragraphs')
+op.add_option('-S', '--no-sort', action='store_false',
+ dest='sort', default=True,
+ help='Do not sort or collate sections')
+op.add_option('-o', '--output', dest='output',
+ default=None, metavar='FILE', help="write output to FILE")
+
+options,args = op.parse_args()
+
+if len(args) > 1:
+ op.error("Too many arguments")
+elif len(args) == 0:
fname = 'ChangeLog'
else:
- fname = sys.argv[1]
+ fname = args[0]
-fname_new = fname+".new"
+if options.output == None:
+ options.output = fname
-sys.stdin = open(fname, 'r')
+if fname != '-':
+ sys.stdin = open(fname, 'r')
nextline = None
+CL = ChangeLog(wrapText=options.wrapText)
+parser = head_parser
+
for line in sys.stdin:
line = line.rstrip()
tp = parser(line)
@@ -295,7 +393,15 @@ for line in sys.stdin:
CL.lint()
-sys.stdout = open(fname_new, 'w')
+if options.output != '-':
+ fname_new = options.output+".new"
+ fname_out = options.output
+ sys.stdout = open(fname_new, 'w')
+else:
+ fname_new = fname_out = None
+
+if options.sort:
+ CL.collateAndSortSections()
CL.dump()
@@ -305,4 +411,5 @@ if nextline is not None:
for line in sys.stdin:
sys.stdout.write(line)
-os.rename(fname_new, fname)
+if fname_new is not None:
+ os.rename(fname_new, fname_out)
diff --git a/scripts/test/cov-diff b/scripts/test/cov-diff
index 33a54802b6..48dbec9d54 100755
--- a/scripts/test/cov-diff
+++ b/scripts/test/cov-diff
@@ -9,8 +9,8 @@ DIRB="$2"
for A in $DIRA/*; do
B=$DIRB/`basename $A`
- perl -pe 's/^\s*\d+:/ 1:/; s/^([^:]+:)[\d\s]+:/$1/;' "$A" > "$A.tmp"
- perl -pe 's/^\s*\d+:/ 1:/; s/^([^:]+:)[\d\s]+:/$1/;' "$B" > "$B.tmp"
+ perl -pe 's/^\s*\d+:/ 1:/; s/^([^:]+:)[\d\s]+:/$1/; s/^ *-:(Runs|Programs):.*//;' "$A" > "$A.tmp"
+ perl -pe 's/^\s*\d+:/ 1:/; s/^([^:]+:)[\d\s]+:/$1/; s/^ *-:(Runs|Programs):.*//;' "$B" > "$B.tmp"
diff -u "$A.tmp" "$B.tmp"
rm "$A.tmp" "$B.tmp"
done
diff --git a/src/common/address.c b/src/common/address.c
index 8591f387e6..07b76597da 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -323,17 +323,23 @@ tor_addr_is_internal_(const tor_addr_t *addr, int for_listening,
{
uint32_t iph4 = 0;
uint32_t iph6[4];
- sa_family_t v_family;
tor_assert(addr);
- v_family = tor_addr_family(addr);
+ sa_family_t v_family = tor_addr_family(addr);
if (v_family == AF_INET) {
iph4 = tor_addr_to_ipv4h(addr);
} else if (v_family == AF_INET6) {
if (tor_addr_is_v4(addr)) { /* v4-mapped */
+ uint32_t *addr32 = NULL;
v_family = AF_INET;
- iph4 = ntohl(tor_addr_to_in6_addr32(addr)[3]);
+ // Work around an incorrect NULL pointer dereference warning in
+ // "clang --analyze" due to limited analysis depth
+ addr32 = tor_addr_to_in6_addr32(addr);
+ // To improve performance, wrap this assertion in:
+ // #if !defined(__clang_analyzer__) || PARANOIA
+ tor_assert(addr32);
+ iph4 = ntohl(addr32[3]);
}
}
@@ -465,7 +471,6 @@ tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
if (!strcasecmpend(address, ".ip6.arpa")) {
const char *cp;
- int i;
int n0, n1;
struct in6_addr in6;
@@ -473,7 +478,7 @@ tor_addr_parse_PTR_name(tor_addr_t *result, const char *address,
return -1;
cp = address;
- for (i = 0; i < 16; ++i) {
+ for (int i = 0; i < 16; ++i) {
n0 = hex_decode_digit(*cp++); /* The low-order nybble appears first. */
if (*cp++ != '.') return -1; /* Then a dot. */
n1 = hex_decode_digit(*cp++); /* The high-order nybble appears first. */
@@ -598,7 +603,7 @@ tor_addr_parse_mask_ports(const char *s,
int any_flag=0, v4map=0;
sa_family_t family;
struct in6_addr in6_tmp;
- struct in_addr in_tmp;
+ struct in_addr in_tmp = { .s_addr = 0 };
tor_assert(s);
tor_assert(addr_out);
@@ -659,7 +664,7 @@ tor_addr_parse_mask_ports(const char *s,
tor_addr_from_ipv4h(addr_out, 0);
any_flag = 1;
} else if (!strcmp(address, "*6") && (flags & TAPMP_EXTENDED_STAR)) {
- static char nil_bytes[16] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
+ static char nil_bytes[16] = { [0]=0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 };
family = AF_INET6;
tor_addr_from_ipv6_bytes(addr_out, nil_bytes);
any_flag = 1;
diff --git a/src/common/address.h b/src/common/address.h
index 8dc63b71c1..42844e8ad1 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -103,7 +103,18 @@ tor_addr_to_ipv4h(const tor_addr_t *a)
static INLINE uint32_t
tor_addr_to_mapped_ipv4h(const tor_addr_t *a)
{
- return a->family == AF_INET6 ? ntohl(tor_addr_to_in6_addr32(a)[3]) : 0;
+ if (a->family == AF_INET6) {
+ uint32_t *addr32 = NULL;
+ // Work around an incorrect NULL pointer dereference warning in
+ // "clang --analyze" due to limited analysis depth
+ addr32 = tor_addr_to_in6_addr32(a);
+ // To improve performance, wrap this assertion in:
+ // #if !defined(__clang_analyzer__) || PARANOIA
+ tor_assert(addr32);
+ return ntohl(addr32[3]);
+ } else {
+ return 0;
+ }
}
/** Return the address family of <b>a</b>. Possible values are:
* AF_INET6, AF_INET, AF_UNSPEC. */
diff --git a/src/common/compat.c b/src/common/compat.c
index 4dd04455a2..b6fdb1ad78 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -2770,14 +2770,24 @@ correct_tm(int islocal, const time_t *timep, struct tm *resultbuf,
const char *outcome;
if (PREDICT_LIKELY(r)) {
- if (r->tm_year > 8099) { /* We can't strftime dates after 9999 CE. */
+ /* We can't strftime dates after 9999 CE, and we want to avoid dates
+ * before 1 CE (avoiding the year 0 issue and negative years). */
+ if (r->tm_year > 8099) {
r->tm_year = 8099;
r->tm_mon = 11;
r->tm_mday = 31;
- r->tm_yday = 365;
+ r->tm_yday = 364;
r->tm_hour = 23;
r->tm_min = 59;
r->tm_sec = 59;
+ } else if (r->tm_year < (1-1900)) {
+ r->tm_year = (1-1900);
+ r->tm_mon = 0;
+ r->tm_mday = 1;
+ r->tm_yday = 0;
+ r->tm_hour = 0;
+ r->tm_min = 0;
+ r->tm_sec = 0;
}
return r;
}
@@ -2791,7 +2801,7 @@ correct_tm(int islocal, const time_t *timep, struct tm *resultbuf,
r->tm_year = 70; /* 1970 CE */
r->tm_mon = 0;
r->tm_mday = 1;
- r->tm_yday = 1;
+ r->tm_yday = 0;
r->tm_hour = 0;
r->tm_min = 0 ;
r->tm_sec = 0;
@@ -2804,7 +2814,7 @@ correct_tm(int islocal, const time_t *timep, struct tm *resultbuf,
r->tm_year = 137; /* 2037 CE */
r->tm_mon = 11;
r->tm_mday = 31;
- r->tm_yday = 365;
+ r->tm_yday = 364;
r->tm_hour = 23;
r->tm_min = 59;
r->tm_sec = 59;
diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c
index 74b54bb855..7e6f304c6b 100644
--- a/src/common/compat_libevent.c
+++ b/src/common/compat_libevent.c
@@ -210,6 +210,9 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg)
} else {
using_iocp_bufferevents = 0;
}
+#elif defined(__COVERITY__)
+ /* Avoid a 'dead code' warning below. */
+ using_threads = ! torcfg->disable_iocp;
#endif
if (!using_threads) {
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 014c83e850..58f20aeb85 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -1684,7 +1684,7 @@ crypto_digest_get_digest(crypto_digest_t *digest,
log_warn(LD_BUG, "Called with unknown algorithm %d", digest->algorithm);
/* If fragile_assert is not enabled, then we should at least not
* leak anything. */
- memset(r, 0xff, sizeof(r));
+ memwipe(r, 0xff, sizeof(r));
tor_fragile_assert();
break;
}
@@ -2454,10 +2454,8 @@ crypto_strongest_rand(uint8_t *out, size_t out_len)
if (!provider_set) {
if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)) {
- if ((unsigned long)GetLastError() != (unsigned long)NTE_BAD_KEYSET) {
- log_warn(LD_CRYPTO, "Can't get CryptoAPI provider [1]");
- return -1;
- }
+ log_warn(LD_CRYPTO, "Can't get CryptoAPI provider [1]");
+ return -1;
}
provider_set = 1;
}
@@ -3001,50 +2999,6 @@ base32_decode(char *dest, size_t destlen, const char *src, size_t srclen)
return 0;
}
-/** Implement RFC2440-style iterated-salted S2K conversion: convert the
- * <b>secret_len</b>-byte <b>secret</b> into a <b>key_out_len</b> byte
- * <b>key_out</b>. As in RFC2440, the first 8 bytes of s2k_specifier
- * are a salt; the 9th byte describes how much iteration to do.
- * Does not support <b>key_out_len</b> &gt; DIGEST_LEN.
- */
-void
-secret_to_key(char *key_out, size_t key_out_len, const char *secret,
- size_t secret_len, const char *s2k_specifier)
-{
- crypto_digest_t *d;
- uint8_t c;
- size_t count, tmplen;
- char *tmp;
- tor_assert(key_out_len < SIZE_T_CEILING);
-
-#define EXPBIAS 6
- c = s2k_specifier[8];
- count = ((uint32_t)16 + (c & 15)) << ((c >> 4) + EXPBIAS);
-#undef EXPBIAS
-
- tor_assert(key_out_len <= DIGEST_LEN);
-
- d = crypto_digest_new();
- tmplen = 8+secret_len;
- tmp = tor_malloc(tmplen);
- memcpy(tmp,s2k_specifier,8);
- memcpy(tmp+8,secret,secret_len);
- secret_len += 8;
- while (count) {
- if (count >= secret_len) {
- crypto_digest_add_bytes(d, tmp, secret_len);
- count -= secret_len;
- } else {
- crypto_digest_add_bytes(d, tmp, count);
- count = 0;
- }
- }
- crypto_digest_get_digest(d, key_out, key_out_len);
- memwipe(tmp, 0, tmplen);
- tor_free(tmp);
- crypto_digest_free(d);
-}
-
/**
* Destroy the <b>sz</b> bytes of data stored at <b>mem</b>, setting them to
* the value <b>byte</b>.
diff --git a/src/common/crypto.h b/src/common/crypto.h
index aa4271aa33..39bbdb5717 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -280,12 +280,6 @@ int digest_from_base64(char *digest, const char *d64);
int digest256_to_base64(char *d64, const char *digest);
int digest256_from_base64(char *digest, const char *d64);
-/** Length of RFC2440-style S2K specifier: the first 8 bytes are a salt, the
- * 9th describes how much iteration to do. */
-#define S2K_SPECIFIER_LEN 9
-void secret_to_key(char *key_out, size_t key_out_len, const char *secret,
- size_t secret_len, const char *s2k_specifier);
-
/** OpenSSL-based utility functions. */
void memwipe(void *mem, uint8_t byte, size_t sz);
diff --git a/src/common/crypto_curve25519.c b/src/common/crypto_curve25519.c
index 9e83440e16..8b8e560c89 100644
--- a/src/common/crypto_curve25519.c
+++ b/src/common/crypto_curve25519.c
@@ -8,6 +8,7 @@
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
+#include "container.h"
#include "crypto.h"
#include "crypto_curve25519.h"
#include "util.h"
@@ -63,26 +64,44 @@ curve25519_public_key_is_ok(const curve25519_public_key_t *key)
return !safe_mem_is_zero(key->public_key, CURVE25519_PUBKEY_LEN);
}
-/** Generate a new keypair and return the secret key. If <b>extra_strong</b>
- * is true, this key is possibly going to get used more than once, so
- * use a better-than-usual RNG. Return 0 on success, -1 on failure. */
+/**
+ * Generate CURVE25519_SECKEY_LEN random bytes in <b>out</b>. If
+ * <b>extra_strong</b> is true, this key is possibly going to get used more
+ * than once, so use a better-than-usual RNG. Return 0 on success, -1 on
+ * failure.
+ *
+ * This function does not adjust the output of the RNG at all; the will caller
+ * will need to clear or set the appropriate bits to make curve25519 work.
+ */
int
-curve25519_secret_key_generate(curve25519_secret_key_t *key_out,
- int extra_strong)
+curve25519_rand_seckey_bytes(uint8_t *out, int extra_strong)
{
uint8_t k_tmp[CURVE25519_SECKEY_LEN];
- if (crypto_rand((char*)key_out->secret_key, CURVE25519_SECKEY_LEN) < 0)
+ if (crypto_rand((char*)out, CURVE25519_SECKEY_LEN) < 0)
return -1;
if (extra_strong && !crypto_strongest_rand(k_tmp, CURVE25519_SECKEY_LEN)) {
/* If they asked for extra-strong entropy and we have some, use it as an
* HMAC key to improve not-so-good entropy rather than using it directly,
* just in case the extra-strong entropy is less amazing than we hoped. */
- crypto_hmac_sha256((char *)key_out->secret_key,
- (const char *)k_tmp, sizeof(k_tmp),
- (const char *)key_out->secret_key, CURVE25519_SECKEY_LEN);
+ crypto_hmac_sha256((char*) out,
+ (const char *)k_tmp, sizeof(k_tmp),
+ (const char *)out, CURVE25519_SECKEY_LEN);
}
memwipe(k_tmp, 0, sizeof(k_tmp));
+ return 0;
+}
+
+/** Generate a new keypair and return the secret key. If <b>extra_strong</b>
+ * is true, this key is possibly going to get used more than once, so
+ * use a better-than-usual RNG. Return 0 on success, -1 on failure. */
+int
+curve25519_secret_key_generate(curve25519_secret_key_t *key_out,
+ int extra_strong)
+{
+ if (curve25519_rand_seckey_bytes(key_out->secret_key, extra_strong) < 0)
+ return -1;
+
key_out->secret_key[0] &= 248;
key_out->secret_key[31] &= 127;
key_out->secret_key[31] |= 64;
@@ -109,69 +128,144 @@ curve25519_keypair_generate(curve25519_keypair_t *keypair_out,
return 0;
}
+/** Write the <b>datalen</b> bytes from <b>data</b> to the file named
+ * <b>fname</b> in the tagged-data format. This format contains a
+ * 32-byte header, followed by the data itself. The header is the
+ * NUL-padded string "== <b>typestring</b>: <b>tag</b> ==". The length
+ * of <b>typestring</b> and <b>tag</b> must therefore be no more than
+ * 24.
+ **/
int
-curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair,
- const char *fname,
- const char *tag)
+crypto_write_tagged_contents_to_file(const char *fname,
+ const char *typestring,
+ const char *tag,
+ const uint8_t *data,
+ size_t datalen)
{
- char contents[32 + CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN];
- int r;
+ char header[32];
+ smartlist_t *chunks = smartlist_new();
+ sized_chunk_t ch0, ch1;
+ int r = -1;
- memset(contents, 0, sizeof(contents));
- tor_snprintf(contents, sizeof(contents), "== c25519v1: %s ==", tag);
- tor_assert(strlen(contents) <= 32);
- memcpy(contents+32, keypair->seckey.secret_key, CURVE25519_SECKEY_LEN);
- memcpy(contents+32+CURVE25519_SECKEY_LEN,
- keypair->pubkey.public_key, CURVE25519_PUBKEY_LEN);
+ memset(header, 0, sizeof(header));
+ if (tor_snprintf(header, sizeof(header),
+ "== %s: %s ==", typestring, tag) < 0)
+ goto end;
+ ch0.bytes = header;
+ ch0.len = 32;
+ ch1.bytes = (const char*) data;
+ ch1.len = datalen;
+ smartlist_add(chunks, &ch0);
+ smartlist_add(chunks, &ch1);
- r = write_bytes_to_file(fname, contents, sizeof(contents), 1);
+ r = write_chunks_to_file(fname, chunks, 1, 0);
- memwipe(contents, 0, sizeof(contents));
+ end:
+ smartlist_free(chunks);
return r;
}
-int
-curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
- char **tag_out,
- const char *fname)
+/** Read a tagged-data file from <b>fname</b> into the
+ * <b>data_out_len</b>-byte buffer in <b>data_out</b>. Check that the
+ * typestring matches <b>typestring</b>; store the tag into a newly allocated
+ * string in <b>tag_out</b>. Return -1 on failure, and the number of bytes of
+ * data on success. */
+ssize_t
+crypto_read_tagged_contents_from_file(const char *fname,
+ const char *typestring,
+ char **tag_out,
+ uint8_t *data_out,
+ ssize_t data_out_len)
{
char prefix[33];
- char *content;
+ char *content = NULL;
struct stat st;
- int r = -1;
+ ssize_t r = -1;
+ size_t st_size = 0;
*tag_out = NULL;
-
st.st_size = 0;
content = read_file_to_str(fname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
if (! content)
goto end;
- if (st.st_size != 32 + CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN)
+ if (st.st_size < 32 || st.st_size > 32 + data_out_len)
goto end;
+ st_size = (size_t)st.st_size;
memcpy(prefix, content, 32);
- prefix[32] = '\0';
- if (strcmpstart(prefix, "== c25519v1: ") ||
- strcmpend(prefix, " =="))
+ prefix[32] = 0;
+ /* Check type, extract tag. */
+ if (strcmpstart(prefix, "== ") || strcmpend(prefix, " ==") ||
+ ! tor_mem_is_zero(prefix+strlen(prefix), 32-strlen(prefix)))
+ goto end;
+
+ if (strcmpstart(prefix+3, typestring) ||
+ 3+strlen(typestring) >= 32 ||
+ strcmpstart(prefix+3+strlen(typestring), ": "))
goto end;
- *tag_out = tor_strndup(prefix+strlen("== c25519v1: "),
- strlen(prefix) - strlen("== c25519v1: =="));
+ *tag_out = tor_strndup(prefix+5+strlen(typestring),
+ strlen(prefix)-8-strlen(typestring));
+
+ memcpy(data_out, content+32, st_size-32);
+ r = st_size - 32;
+
+ end:
+ if (content)
+ memwipe(content, 0, st_size);
+ tor_free(content);
+ return r;
+}
+
+/** DOCDOC */
+int
+curve25519_keypair_write_to_file(const curve25519_keypair_t *keypair,
+ const char *fname,
+ const char *tag)
+{
+ uint8_t contents[CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN];
+ int r;
+
+ memcpy(contents, keypair->seckey.secret_key, CURVE25519_SECKEY_LEN);
+ memcpy(contents+CURVE25519_SECKEY_LEN,
+ keypair->pubkey.public_key, CURVE25519_PUBKEY_LEN);
+
+ r = crypto_write_tagged_contents_to_file(fname,
+ "c25519v1",
+ tag,
+ contents,
+ sizeof(contents));
+
+ memwipe(contents, 0, sizeof(contents));
+ return r;
+}
+
+/** DOCDOC */
+int
+curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
+ char **tag_out,
+ const char *fname)
+{
+ uint8_t content[CURVE25519_SECKEY_LEN + CURVE25519_PUBKEY_LEN];
+ ssize_t len;
+ int r = -1;
+
+ len = crypto_read_tagged_contents_from_file(fname, "c25519v1", tag_out,
+ content, sizeof(content));
+ if (len != sizeof(content))
+ goto end;
- memcpy(keypair_out->seckey.secret_key, content+32, CURVE25519_SECKEY_LEN);
+ memcpy(keypair_out->seckey.secret_key, content, CURVE25519_SECKEY_LEN);
curve25519_public_key_generate(&keypair_out->pubkey, &keypair_out->seckey);
if (tor_memneq(keypair_out->pubkey.public_key,
- content + 32 + CURVE25519_SECKEY_LEN,
+ content + CURVE25519_SECKEY_LEN,
CURVE25519_PUBKEY_LEN))
goto end;
r = 0;
end:
- if (content) {
- memwipe(content, 0, (size_t) st.st_size);
- tor_free(content);
- }
+ memwipe(content, 0, sizeof(content));
if (r != 0) {
memset(keypair_out, 0, sizeof(*keypair_out));
tor_free(*tag_out);
diff --git a/src/common/crypto_curve25519.h b/src/common/crypto_curve25519.h
index 57018ac2f5..404f99c18e 100644
--- a/src/common/crypto_curve25519.h
+++ b/src/common/crypto_curve25519.h
@@ -57,6 +57,8 @@ int curve25519_keypair_read_from_file(curve25519_keypair_t *keypair_out,
char **tag_out,
const char *fname);
+int curve25519_rand_seckey_bytes(uint8_t *out, int extra_strong);
+
#ifdef CRYPTO_CURVE25519_PRIVATE
STATIC int curve25519_impl(uint8_t *output, const uint8_t *secret,
const uint8_t *basepoint);
@@ -70,5 +72,17 @@ int curve25519_public_from_base64(curve25519_public_key_t *pkey,
int curve25519_public_to_base64(char *output,
const curve25519_public_key_t *pkey);
+int crypto_write_tagged_contents_to_file(const char *fname,
+ const char *typestring,
+ const char *tag,
+ const uint8_t *data,
+ size_t datalen);
+
+ssize_t crypto_read_tagged_contents_from_file(const char *fname,
+ const char *typestring,
+ char **tag_out,
+ uint8_t *data_out,
+ ssize_t data_out_len);
+
#endif
diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c
new file mode 100644
index 0000000000..408c12b4fd
--- /dev/null
+++ b/src/common/crypto_ed25519.c
@@ -0,0 +1,353 @@
+/* Copyright (c) 2013, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/* Wrapper code for an ed25519 implementation. */
+
+#include "orconfig.h"
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#include "crypto.h"
+
+#include "crypto_curve25519.h"
+#include "crypto_ed25519.h"
+#include "torlog.h"
+#include "util.h"
+
+#include "ed25519/ref10/ed25519_ref10.h"
+
+#include <openssl/sha.h>
+
+/**
+ * Initialize a new ed25519 secret key in <b>seckey_out</b>. If
+ * <b>extra_strong</b>, take the RNG inputs directly from the operating
+ * system. Return 0 on success, -1 on failure.
+ */
+int
+ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out,
+ int extra_strong)
+{
+ int r;
+ uint8_t seed[32];
+ if (! extra_strong || crypto_strongest_rand(seed, sizeof(seed)) < 0)
+ crypto_rand((char*)seed, sizeof(seed));
+
+ r = ed25519_ref10_seckey_expand(seckey_out->seckey, seed);
+ memwipe(seed, 0, sizeof(seed));
+
+ return r < 0 ? -1 : 0;
+}
+
+/**
+ * Given a 32-byte random seed in <b>seed</b>, expand it into an ed25519
+ * secret key in <b>seckey_out</b>. Return 0 on success, -1 on failure.
+ */
+int
+ed25519_secret_key_from_seed(ed25519_secret_key_t *seckey_out,
+ const uint8_t *seed)
+{
+ if (ed25519_ref10_seckey_expand(seckey_out->seckey, seed) < 0)
+ return -1;
+ return 0;
+}
+
+/**
+ * Given a secret key in <b>seckey</b>, expand it into an
+ * ed25519 public key. Return 0 on success, -1 on failure.
+ */
+int
+ed25519_public_key_generate(ed25519_public_key_t *pubkey_out,
+ const ed25519_secret_key_t *seckey)
+{
+ if (ed25519_ref10_pubkey(pubkey_out->pubkey, seckey->seckey) < 0)
+ return -1;
+ return 0;
+}
+
+/** Generate a new ed25519 keypair in <b>keypair_out</b>. If
+ * <b>extra_strong</b> is set, try to mix some system entropy into the key
+ * generation process. Return 0 on success, -1 on failure. */
+int
+ed25519_keypair_generate(ed25519_keypair_t *keypair_out, int extra_strong)
+{
+ if (ed25519_secret_key_generate(&keypair_out->seckey, extra_strong) < 0)
+ return -1;
+ if (ed25519_public_key_generate(&keypair_out->pubkey,
+ &keypair_out->seckey)<0)
+ return -1;
+ return 0;
+}
+
+/**
+ * Set <b>signature_out</b> to a signature of the <b>len</b>-byte message
+ * <b>msg</b>, using the secret and public key in <b>keypair</b>.
+ */
+int
+ed25519_sign(ed25519_signature_t *signature_out,
+ const uint8_t *msg, size_t len,
+ const ed25519_keypair_t *keypair)
+{
+
+ if (ed25519_ref10_sign(signature_out->sig, msg, len,
+ keypair->seckey.seckey,
+ keypair->pubkey.pubkey) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Check whether if <b>signature</b> is a valid signature for the
+ * <b>len</b>-byte message in <b>msg</b> made with the key <b>pubkey</b>.
+ *
+ * Return 0 if the signature is valid; -1 if it isn't.
+ */
+int
+ed25519_checksig(const ed25519_signature_t *signature,
+ const uint8_t *msg, size_t len,
+ const ed25519_public_key_t *pubkey)
+{
+ return
+ ed25519_ref10_open(signature->sig, msg, len, pubkey->pubkey) < 0 ? -1 : 0;
+}
+
+/** Validate every signature among those in <b>checkable</b>, which contains
+ * exactly <b>n_checkable</b> elements. If <b>okay_out</b> is non-NULL, set
+ * the i'th element of <b>okay_out</b> to 1 if the i'th element of
+ * <b>checkable</b> is valid, and to 0 otherwise. Return 0 if every signature
+ * was valid. Otherwise return -N, where N is the number of invalid
+ * signatures.
+ */
+int
+ed25519_checksig_batch(int *okay_out,
+ const ed25519_checkable_t *checkable,
+ int n_checkable)
+{
+ int res, i;
+
+ res = 0;
+ for (i = 0; i < n_checkable; ++i) {
+ const ed25519_checkable_t *ch = &checkable[i];
+ int r = ed25519_checksig(&ch->signature, ch->msg, ch->len, ch->pubkey);
+ if (r < 0)
+ --res;
+ if (okay_out)
+ okay_out[i] = (r == 0);
+ }
+
+#if 0
+ /* This is how we'd do it if we were using ed25519_donna. I'll keep this
+ * code around here in case we ever do that. */
+ const uint8_t **ms;
+ size_t *lens;
+ const uint8_t **pks;
+ const uint8_t **sigs;
+ int *oks;
+
+ ms = tor_malloc(sizeof(uint8_t*)*n_checkable);
+ lens = tor_malloc(sizeof(size_t)*n_checkable);
+ pks = tor_malloc(sizeof(uint8_t*)*n_checkable);
+ sigs = tor_malloc(sizeof(uint8_t*)*n_checkable);
+ oks = okay_out ? okay_out : tor_malloc(sizeof(int)*n_checkable);
+
+ for (i = 0; i < n_checkable; ++i) {
+ ms[i] = checkable[i].msg;
+ lens[i] = checkable[i].len;
+ pks[i] = checkable[i].pubkey->pubkey;
+ sigs[i] = checkable[i].signature.sig;
+ oks[i] = 0;
+ }
+
+ ed25519_sign_open_batch_donna_fb(ms, lens, pks, sigs, n_checkable, oks);
+
+ res = 0;
+ for (i = 0; i < n_checkable; ++i) {
+ if (!oks[i])
+ --res;
+ }
+
+ tor_free(ms);
+ tor_free(lens);
+ tor_free(pks);
+ if (! okay_out)
+ tor_free(oks);
+#endif
+
+ return res;
+}
+
+/**
+ * Given a curve25519 keypair in <b>inp</b>, generate a corresponding
+ * ed25519 keypair in <b>out</b>, and set <b>signbit_out</b> to the
+ * sign bit of the X coordinate of the ed25519 key.
+ *
+ * NOTE THAT IT IS PROBABLY NOT SAFE TO USE THE GENERATED KEY FOR ANYTHING
+ * OUTSIDE OF WHAT'S PRESENTED IN PROPOSAL 228. In particular, it's probably
+ * not a great idea to use it to sign attacker-supplied anything.
+ */
+int
+ed25519_keypair_from_curve25519_keypair(ed25519_keypair_t *out,
+ int *signbit_out,
+ const curve25519_keypair_t *inp)
+{
+ const char string[] = "Derive high part of ed25519 key from curve25519 key";
+ ed25519_public_key_t pubkey_check;
+ SHA512_CTX ctx;
+ uint8_t sha512_output[64];
+
+ memcpy(out->seckey.seckey, inp->seckey.secret_key, 32);
+ SHA512_Init(&ctx);
+ SHA512_Update(&ctx, out->seckey.seckey, 32);
+ SHA512_Update(&ctx, string, sizeof(string));
+ SHA512_Final(sha512_output, &ctx);
+ memcpy(out->seckey.seckey + 32, sha512_output, 32);
+
+ ed25519_public_key_generate(&out->pubkey, &out->seckey);
+
+ *signbit_out = out->pubkey.pubkey[31] >> 7;
+
+ ed25519_public_key_from_curve25519_public_key(&pubkey_check, &inp->pubkey,
+ *signbit_out);
+
+ tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32));
+
+ memwipe(&pubkey_check, 0, sizeof(pubkey_check));
+ memwipe(&ctx, 0, sizeof(ctx));
+ memwipe(sha512_output, 0, sizeof(sha512_output));
+
+ return 0;
+}
+
+/**
+ * Given a curve25519 public key and sign bit of X coordinate of the ed25519
+ * public key, generate the corresponding ed25519 public key.
+ */
+int
+ed25519_public_key_from_curve25519_public_key(ed25519_public_key_t *pubkey,
+ const curve25519_public_key_t *pubkey_in,
+ int signbit)
+{
+ return ed25519_ref10_pubkey_from_curve25519_pubkey(pubkey->pubkey,
+ pubkey_in->public_key,
+ signbit);
+}
+
+/**
+ * Given an ed25519 keypair in <b>inp</b>, generate a corresponding
+ * ed25519 keypair in <b>out</b>, blinded by the corresponding 32-byte input
+ * in 'param'.
+ *
+ * Tor uses key blinding for the "next-generation" hidden services design:
+ * service descriptors are encrypted with a key derived from the service's
+ * long-term public key, and then signed with (and stored at a position
+ * indexed by) a short-term key derived by blinding the long-term keys.
+ */
+int
+ed25519_keypair_blind(ed25519_keypair_t *out,
+ const ed25519_keypair_t *inp,
+ const uint8_t *param)
+{
+ ed25519_public_key_t pubkey_check;
+
+ ed25519_ref10_blind_secret_key(out->seckey.seckey,
+ inp->seckey.seckey, param);
+
+ ed25519_public_blind(&pubkey_check, &inp->pubkey, param);
+ ed25519_public_key_generate(&out->pubkey, &out->seckey);
+
+ tor_assert(fast_memeq(pubkey_check.pubkey, out->pubkey.pubkey, 32));
+
+ memwipe(&pubkey_check, 0, sizeof(pubkey_check));
+
+ return 0;
+}
+
+/**
+ * Given an ed25519 public key in <b>inp</b>, generate a corresponding blinded
+ * public key in <b>out</b>, blinded with the 32-byte parameter in
+ * <b>param</b>. Return 0 on sucess, -1 on railure.
+ */
+int
+ed25519_public_blind(ed25519_public_key_t *out,
+ const ed25519_public_key_t *inp,
+ const uint8_t *param)
+{
+ ed25519_ref10_blind_public_key(out->pubkey, inp->pubkey, param);
+ return 0;
+}
+
+/**
+ * Store seckey unencrypted to <b>filename</b>, marking it with <b>tag</b>.
+ * Return 0 on success, -1 on failure.
+ */
+int
+ed25519_seckey_write_to_file(const ed25519_secret_key_t *seckey,
+ const char *filename,
+ const char *tag)
+{
+ return crypto_write_tagged_contents_to_file(filename,
+ "ed25519v1-secret",
+ tag,
+ seckey->seckey,
+ sizeof(seckey->seckey));
+}
+
+/**
+ * Read seckey unencrypted from <b>filename</b>, storing it into
+ * <b>seckey_out</b>. Set *<b>tag_out</> to the tag it was marked with.
+ * Return 0 on success, -1 on failure.
+ */
+int
+ed25519_seckey_read_from_file(ed25519_secret_key_t *seckey_out,
+ char **tag_out,
+ const char *filename)
+{
+ ssize_t len;
+
+ len = crypto_read_tagged_contents_from_file(filename, "ed25519v1-secret",
+ tag_out, seckey_out->seckey,
+ sizeof(seckey_out->seckey));
+ if (len != sizeof(seckey_out->seckey))
+ return -1;
+
+ return 0;
+}
+
+/**
+ * Store pubkey unencrypted to <b>filename</b>, marking it with <b>tag</b>.
+ * Return 0 on success, -1 on failure.
+ */
+int
+ed25519_pubkey_write_to_file(const ed25519_public_key_t *pubkey,
+ const char *filename,
+ const char *tag)
+{
+ return crypto_write_tagged_contents_to_file(filename,
+ "ed25519v1-public",
+ tag,
+ pubkey->pubkey,
+ sizeof(pubkey->pubkey));
+}
+
+/**
+ * Store pubkey unencrypted to <b>filename</b>, marking it with <b>tag</b>.
+ * Return 0 on success, -1 on failure.
+ */
+int
+ed25519_pubkey_read_from_file(ed25519_public_key_t *pubkey_out,
+ char **tag_out,
+ const char *filename)
+{
+ ssize_t len;
+
+ len = crypto_read_tagged_contents_from_file(filename, "ed25519v1-public",
+ tag_out, pubkey_out->pubkey,
+ sizeof(pubkey_out->pubkey));
+ if (len != sizeof(pubkey_out->pubkey))
+ return -1;
+
+ return 0;
+}
+
diff --git a/src/common/crypto_ed25519.h b/src/common/crypto_ed25519.h
new file mode 100644
index 0000000000..13b05c7c1e
--- /dev/null
+++ b/src/common/crypto_ed25519.h
@@ -0,0 +1,116 @@
+/* Copyright (c) 2012-2013, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_CRYPTO_ED25519_H
+#define TOR_CRYPTO_ED25519_H
+
+#include "testsupport.h"
+#include "torint.h"
+
+#define ED25519_PUBKEY_LEN 32
+#define ED25519_SECKEY_LEN 64
+#define ED25519_SECKEY_SEED_LEN 32
+#define ED25519_SIG_LEN 64
+
+/** An Ed25519 signature. */
+typedef struct {
+ uint8_t sig[ED25519_SIG_LEN];
+} ed25519_signature_t;
+
+/** An Ed25519 public key */
+typedef struct {
+ uint8_t pubkey[ED25519_PUBKEY_LEN];
+} ed25519_public_key_t;
+
+/** An Ed25519 secret key */
+typedef struct {
+ /** Note that we store secret keys in an expanded format that doesn't match
+ * the format from standard ed25519. Ed25519 stores a 32-byte value k and
+ * expands it into a 64-byte H(k), using the first 32 bytes for a multiplier
+ * of the base point, and second 32 bytes as an input to a hash function
+ * for deriving r. But because we implement key blinding, we need to store
+ * keys in the 64-byte expanded form. */
+ uint8_t seckey[ED25519_SECKEY_LEN];
+} ed25519_secret_key_t;
+
+/** An Ed25519 keypair. */
+typedef struct {
+ ed25519_public_key_t pubkey;
+ ed25519_secret_key_t seckey;
+} ed25519_keypair_t;
+
+#ifdef CURVE25519_ENABLED
+int ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out,
+ int extra_strong);
+int ed25519_secret_key_from_seed(ed25519_secret_key_t *seckey_out,
+ const uint8_t *seed);
+
+int ed25519_public_key_generate(ed25519_public_key_t *pubkey_out,
+ const ed25519_secret_key_t *seckey);
+int ed25519_keypair_generate(ed25519_keypair_t *keypair_out, int extra_strong);
+int ed25519_sign(ed25519_signature_t *signature_out,
+ const uint8_t *msg, size_t len,
+ const ed25519_keypair_t *key);
+int ed25519_checksig(const ed25519_signature_t *signature,
+ const uint8_t *msg, size_t len,
+ const ed25519_public_key_t *pubkey);
+
+/**
+ * A collection of information necessary to check an Ed25519 signature. Used
+ * for batch verification.
+ */
+typedef struct {
+ /** The public key that supposedly generated the signature. */
+ ed25519_public_key_t *pubkey;
+ /** The signature to check. */
+ ed25519_signature_t signature;
+ /** The message that the signature is supposed to have been applied to. */
+ const uint8_t *msg;
+ /** The length of the message. */
+ size_t len;
+} ed25519_checkable_t;
+
+int ed25519_checksig_batch(int *okay_out,
+ const ed25519_checkable_t *checkable,
+ int n_checkable);
+
+int ed25519_keypair_from_curve25519_keypair(ed25519_keypair_t *out,
+ int *signbit_out,
+ const curve25519_keypair_t *inp);
+
+int ed25519_public_key_from_curve25519_public_key(ed25519_public_key_t *pubkey,
+ const curve25519_public_key_t *pubkey_in,
+ int signbit);
+int ed25519_keypair_blind(ed25519_keypair_t *out,
+ const ed25519_keypair_t *inp,
+ const uint8_t *param);
+int ed25519_public_blind(ed25519_public_key_t *out,
+ const ed25519_public_key_t *inp,
+ const uint8_t *param);
+
+#endif
+
+#define ED25519_BASE64_LEN 43
+
+int ed25519_public_from_base64(ed25519_public_key_t *pkey,
+ const char *input);
+int ed25519_public_to_base64(char *output,
+ const ed25519_public_key_t *pkey);
+
+/* XXXX read encrypted, write encrypted. */
+
+int ed25519_seckey_write_to_file(const ed25519_secret_key_t *seckey,
+ const char *filename,
+ const char *tag);
+int ed25519_seckey_read_from_file(ed25519_secret_key_t *seckey_out,
+ char **tag_out,
+ const char *filename);
+int ed25519_pubkey_write_to_file(const ed25519_public_key_t *pubkey,
+ const char *filename,
+ const char *tag);
+int ed25519_pubkey_read_from_file(ed25519_public_key_t *pubkey_out,
+ char **tag_out,
+ const char *filename);
+
+#endif
+
diff --git a/src/common/crypto_format.c b/src/common/crypto_format.c
index be669c8d2b..a9f104cab2 100644
--- a/src/common/crypto_format.c
+++ b/src/common/crypto_format.c
@@ -9,6 +9,7 @@
#endif
#include "crypto.h"
#include "crypto_curve25519.h"
+#include "crypto_ed25519.h"
#include "util.h"
#include "torlog.h"
@@ -43,3 +44,24 @@ curve25519_public_from_base64(curve25519_public_key_t *pkey,
}
}
+/** Try to decode the string <b>input</b> into an ed25519 public key. On
+ * success, store the value in <b>pkey</b> and return 0. Otherwise return
+ * -1. */
+int
+ed25519_public_from_base64(ed25519_public_key_t *pkey,
+ const char *input)
+{
+ return digest256_from_base64((char*)pkey->pubkey, input);
+}
+
+/** Encode the public key <b>pkey</b> into the buffer at <b>output</b>,
+ * which must have space for ED25519_BASE64_LEN bytes of encoded key,
+ * plus one byte for a terminating NUL. Return 0 on success, -1 on failure.
+ */
+int
+ed25519_public_to_base64(char *output,
+ const ed25519_public_key_t *pkey)
+{
+ return digest256_to_base64(output, (const char *)pkey->pubkey);
+}
+
diff --git a/src/common/crypto_pwbox.c b/src/common/crypto_pwbox.c
new file mode 100644
index 0000000000..91659db2bc
--- /dev/null
+++ b/src/common/crypto_pwbox.c
@@ -0,0 +1,187 @@
+
+#include "crypto.h"
+#include "crypto_s2k.h"
+#include "crypto_pwbox.h"
+#include "di_ops.h"
+#include "util.h"
+#include "pwbox.h"
+
+/* 8 bytes "TORBOX00"
+ 1 byte: header len (H)
+ H bytes: header, denoting secret key algorithm.
+ 16 bytes: IV
+ Round up to multiple of 128 bytes, then encrypt:
+ 4 bytes: data len
+ data
+ zeros
+ 32 bytes: HMAC-SHA256 of all previous bytes.
+*/
+
+#define MAX_OVERHEAD (S2K_MAXLEN + 8 + 1 + 32 + CIPHER_IV_LEN)
+
+/**
+ * Make an authenticated passphrase-encrypted blob to encode the
+ * <b>input_len</b> bytes in <b>input</b> using the passphrase
+ * <b>secret</b> of <b>secret_len</b> bytes. Allocate a new chunk of memory
+ * to hold the encrypted data, and store a pointer to that memory in
+ * *<b>out</b>, and its size in <b>outlen_out</b>. Use <b>s2k_flags</b> as an
+ * argument to the passphrase-hashing function.
+ */
+int
+crypto_pwbox(uint8_t **out, size_t *outlen_out,
+ const uint8_t *input, size_t input_len,
+ const char *secret, size_t secret_len,
+ unsigned s2k_flags)
+{
+ uint8_t *result = NULL, *encrypted_portion;
+ size_t encrypted_len = 128 * CEIL_DIV(input_len+4, 128);
+ ssize_t result_len;
+ int spec_len;
+ uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN];
+ pwbox_encoded_t *enc = NULL;
+ ssize_t enc_len;
+
+ crypto_cipher_t *cipher;
+ int rv;
+
+ enc = pwbox_encoded_new();
+
+ pwbox_encoded_setlen_skey_header(enc, S2K_MAXLEN);
+
+ spec_len = secret_to_key_make_specifier(
+ pwbox_encoded_getarray_skey_header(enc),
+ S2K_MAXLEN,
+ s2k_flags);
+ if (spec_len < 0 || spec_len > S2K_MAXLEN)
+ goto err;
+ pwbox_encoded_setlen_skey_header(enc, spec_len);
+ enc->header_len = spec_len;
+
+ crypto_rand((char*)enc->iv, sizeof(enc->iv));
+
+ pwbox_encoded_setlen_data(enc, encrypted_len);
+ encrypted_portion = pwbox_encoded_getarray_data(enc);
+
+ set_uint32(encrypted_portion, htonl(input_len));
+ memcpy(encrypted_portion+4, input, input_len);
+
+ /* Now that all the data is in position, derive some keys, encrypt, and
+ * digest */
+ if (secret_to_key_derivekey(keys, sizeof(keys),
+ pwbox_encoded_getarray_skey_header(enc),
+ spec_len,
+ secret, secret_len) < 0)
+ goto err;
+
+ cipher = crypto_cipher_new_with_iv((char*)keys, (char*)enc->iv);
+ crypto_cipher_crypt_inplace(cipher, (char*)encrypted_portion, encrypted_len);
+ crypto_cipher_free(cipher);
+
+ result_len = pwbox_encoded_encoded_len(enc);
+ if (result_len < 0)
+ goto err;
+ result = tor_malloc(result_len);
+ enc_len = pwbox_encoded_encode(result, result_len, enc);
+ if (enc_len < 0)
+ goto err;
+ tor_assert(enc_len == result_len);
+
+ crypto_hmac_sha256((char*) result + result_len - 32,
+ (const char*)keys + CIPHER_KEY_LEN,
+ DIGEST256_LEN,
+ (const char*)result,
+ result_len - 32);
+
+ *out = result;
+ *outlen_out = result_len;
+ rv = 0;
+ goto out;
+
+ err:
+ tor_free(result);
+ rv = -1;
+
+ out:
+ pwbox_encoded_free(enc);
+ memwipe(keys, 0, sizeof(keys));
+ return rv;
+}
+
+/**
+ * Try to decrypt the passphrase-encrypted blob of <b>input_len</b> bytes in
+ * <b>input</b> using the passphrase <b>secret</b> of <b>secret_len</b> bytes.
+ * On success, return 0 and allocate a new chunk of memory to hold the
+ * decrypted data, and store a pointer to that memory in *<b>out</b>, and its
+ * size in <b>outlen_out</b>. On failure, return UNPWBOX_BAD_SECRET if
+ * the passphrase might have been wrong, and UNPWBOX_CORRUPT if the object is
+ * definitely corrupt.
+ */
+int
+crypto_unpwbox(uint8_t **out, size_t *outlen_out,
+ const uint8_t *inp, size_t input_len,
+ const char *secret, size_t secret_len)
+{
+ uint8_t *result = NULL;
+ const uint8_t *encrypted;
+ uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN];
+ uint8_t hmac[DIGEST256_LEN];
+ uint32_t result_len;
+ size_t encrypted_len;
+ crypto_cipher_t *cipher = NULL;
+ int rv = UNPWBOX_CORRUPTED;
+ ssize_t got_len;
+
+ pwbox_encoded_t *enc = NULL;
+
+ got_len = pwbox_encoded_parse(&enc, inp, input_len);
+ if (got_len < 0 || (size_t)got_len != input_len)
+ goto err;
+
+ /* Now derive the keys and check the hmac. */
+ if (secret_to_key_derivekey(keys, sizeof(keys),
+ pwbox_encoded_getarray_skey_header(enc),
+ pwbox_encoded_getlen_skey_header(enc),
+ secret, secret_len) < 0)
+ goto err;
+
+ crypto_hmac_sha256((char *)hmac,
+ (const char*)keys + CIPHER_KEY_LEN, DIGEST256_LEN,
+ (const char*)inp, input_len - DIGEST256_LEN);
+
+ if (tor_memneq(hmac, enc->hmac, DIGEST256_LEN)) {
+ rv = UNPWBOX_BAD_SECRET;
+ goto err;
+ }
+
+ /* How long is the plaintext? */
+ encrypted = pwbox_encoded_getarray_data(enc);
+ encrypted_len = pwbox_encoded_getlen_data(enc);
+ if (encrypted_len < 4)
+ goto err;
+
+ cipher = crypto_cipher_new_with_iv((char*)keys, (char*)enc->iv);
+ crypto_cipher_decrypt(cipher, (char*)&result_len, (char*)encrypted, 4);
+ result_len = ntohl(result_len);
+ if (encrypted_len < result_len + 4)
+ goto err;
+
+ /* Allocate a buffer and decrypt */
+ result = tor_malloc_zero(result_len);
+ crypto_cipher_decrypt(cipher, (char*)result, (char*)encrypted+4, result_len);
+
+ *out = result;
+ *outlen_out = result_len;
+
+ rv = UNPWBOX_OKAY;
+ goto out;
+
+ err:
+ tor_free(result);
+
+ out:
+ crypto_cipher_free(cipher);
+ pwbox_encoded_free(enc);
+ memwipe(keys, 0, sizeof(keys));
+ return rv;
+}
+
diff --git a/src/common/crypto_pwbox.h b/src/common/crypto_pwbox.h
new file mode 100644
index 0000000000..aadd477078
--- /dev/null
+++ b/src/common/crypto_pwbox.h
@@ -0,0 +1,20 @@
+#ifndef CRYPTO_PWBOX_H_INCLUDED_
+#define CRYPTO_PWBOX_H_INCLUDED_
+
+#include "torint.h"
+
+#define UNPWBOX_OKAY 0
+#define UNPWBOX_BAD_SECRET -1
+#define UNPWBOX_CORRUPTED -2
+
+int crypto_pwbox(uint8_t **out, size_t *outlen_out,
+ const uint8_t *inp, size_t input_len,
+ const char *secret, size_t secret_len,
+ unsigned s2k_flags);
+
+int crypto_unpwbox(uint8_t **out, size_t *outlen_out,
+ const uint8_t *inp, size_t input_len,
+ const char *secret, size_t secret_len);
+
+#endif
+
diff --git a/src/common/crypto_s2k.c b/src/common/crypto_s2k.c
new file mode 100644
index 0000000000..aef8436ad9
--- /dev/null
+++ b/src/common/crypto_s2k.c
@@ -0,0 +1,460 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2013, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define CRYPTO_S2K_PRIVATE
+
+#include "crypto.h"
+#include "util.h"
+#include "compat.h"
+#include "crypto_s2k.h"
+
+#include <openssl/evp.h>
+
+#ifdef HAVE_LIBSCRYPT_H
+#define HAVE_SCRYPT
+#include <libscrypt.h>
+#endif
+
+/* Encoded secrets take the form:
+
+ u8 type;
+ u8 salt_and_parameters[depends on type];
+ u8 key[depends on type];
+
+ As a special case, if the encoded secret is exactly 29 bytes long,
+ type 0 is understood.
+
+ Recognized types are:
+ 00 -- RFC2440. salt_and_parameters is 9 bytes. key is 20 bytes.
+ salt_and_parameters is 8 bytes random salt,
+ 1 byte iteration info.
+ 01 -- PKBDF2_SHA1. salt_and_parameters is 17 bytes. key is 20 bytes.
+ salt_and_parameters is 16 bytes random salt,
+ 1 byte iteration info.
+ 02 -- SCRYPT_SALSA208_SHA256. salt_and_parameters is 18 bytes. key is
+ 32 bytes.
+ salt_and_parameters is 18 bytes random salt, 2 bytes iteration
+ info.
+*/
+
+#define S2K_TYPE_RFC2440 0
+#define S2K_TYPE_PBKDF2 1
+#define S2K_TYPE_SCRYPT 2
+
+#define PBKDF2_SPEC_LEN 17
+#define PBKDF2_KEY_LEN 20
+
+#define SCRYPT_SPEC_LEN 18
+#define SCRYPT_KEY_LEN 32
+
+/** Given an algorithm ID (one of S2K_TYPE_*), return the length of the
+ * specifier part of it, without the prefix type byte. */
+static int
+secret_to_key_spec_len(uint8_t type)
+{
+ switch (type) {
+ case S2K_TYPE_RFC2440:
+ return S2K_RFC2440_SPECIFIER_LEN;
+ case S2K_TYPE_PBKDF2:
+ return PBKDF2_SPEC_LEN;
+ case S2K_TYPE_SCRYPT:
+ return SCRYPT_SPEC_LEN;
+ default:
+ return -1;
+ }
+}
+
+/** Given an algorithm ID (one of S2K_TYPE_*), return the length of the
+ * its preferred output. */
+static int
+secret_to_key_key_len(uint8_t type)
+{
+ switch (type) {
+ case S2K_TYPE_RFC2440:
+ return DIGEST_LEN;
+ case S2K_TYPE_PBKDF2:
+ return DIGEST_LEN;
+ case S2K_TYPE_SCRYPT:
+ return DIGEST256_LEN;
+ default:
+ return -1;
+ }
+}
+
+/** Given a specifier in <b>spec_and_key</b> of length
+ * <b>spec_and_key_len</b>, along with its prefix algorithm ID byte, and along
+ * with a key if <b>key_included</b> is true, check whether the whole
+ * specifier-and-key is of valid length, and return the algorithm type if it
+ * is. Set *<b>legacy_out</b> to 1 iff this is a legacy password hash or
+ * legacy specifier. Return an error code on failure.
+ */
+static int
+secret_to_key_get_type(const uint8_t *spec_and_key, size_t spec_and_key_len,
+ int key_included, int *legacy_out)
+{
+ size_t legacy_len = S2K_RFC2440_SPECIFIER_LEN;
+ uint8_t type;
+ int total_len;
+
+ if (key_included)
+ legacy_len += DIGEST_LEN;
+
+ if (spec_and_key_len == legacy_len) {
+ *legacy_out = 1;
+ return S2K_TYPE_RFC2440;
+ }
+
+ *legacy_out = 0;
+ if (spec_and_key_len == 0)
+ return S2K_BAD_LEN;
+
+ type = spec_and_key[0];
+ total_len = secret_to_key_spec_len(type);
+ if (total_len < 0)
+ return S2K_BAD_ALGORITHM;
+ if (key_included) {
+ int keylen = secret_to_key_key_len(type);
+ if (keylen < 0)
+ return S2K_BAD_ALGORITHM;
+ total_len += keylen;
+ }
+
+ if ((size_t)total_len + 1 == spec_and_key_len)
+ return type;
+ else
+ return S2K_BAD_LEN;
+}
+
+/**
+ * Write a new random s2k specifier of type <b>type</b>, without prefixing
+ * type byte, to <b>spec_out</b>, which must have enough room. May adjust
+ * parameter choice based on <b>flags</b>.
+ */
+static int
+make_specifier(uint8_t *spec_out, uint8_t type, unsigned flags)
+{
+ int speclen = secret_to_key_spec_len(type);
+ if (speclen < 0)
+ return S2K_BAD_ALGORITHM;
+
+ crypto_rand((char*)spec_out, speclen);
+ switch (type) {
+ case S2K_TYPE_RFC2440:
+ /* Hash 64 k of data. */
+ spec_out[S2K_RFC2440_SPECIFIER_LEN-1] = 96;
+ break;
+ case S2K_TYPE_PBKDF2:
+ /* 131 K iterations */
+ spec_out[PBKDF2_SPEC_LEN-1] = 17;
+ break;
+ case S2K_TYPE_SCRYPT:
+ if (flags & S2K_FLAG_LOW_MEM) {
+ /* N = 1<<12 */
+ spec_out[SCRYPT_SPEC_LEN-2] = 12;
+ } else {
+ /* N = 1<<15 */
+ spec_out[SCRYPT_SPEC_LEN-2] = 15;
+ }
+ /* r = 8; p = 2. */
+ spec_out[SCRYPT_SPEC_LEN-1] = (3u << 4) | (1u << 0);
+ break;
+ default:
+ tor_fragile_assert();
+ return S2K_BAD_ALGORITHM;
+ }
+
+ return speclen;
+}
+
+/** Implement RFC2440-style iterated-salted S2K conversion: convert the
+ * <b>secret_len</b>-byte <b>secret</b> into a <b>key_out_len</b> byte
+ * <b>key_out</b>. As in RFC2440, the first 8 bytes of s2k_specifier
+ * are a salt; the 9th byte describes how much iteration to do.
+ * If <b>key_out_len</b> &gt; DIGEST_LEN, use HDKF to expand the result.
+ */
+void
+secret_to_key_rfc2440(char *key_out, size_t key_out_len, const char *secret,
+ size_t secret_len, const char *s2k_specifier)
+{
+ crypto_digest_t *d;
+ uint8_t c;
+ size_t count, tmplen;
+ char *tmp;
+ uint8_t buf[DIGEST_LEN];
+ tor_assert(key_out_len < SIZE_T_CEILING);
+
+#define EXPBIAS 6
+ c = s2k_specifier[8];
+ count = ((uint32_t)16 + (c & 15)) << ((c >> 4) + EXPBIAS);
+#undef EXPBIAS
+
+ d = crypto_digest_new();
+ tmplen = 8+secret_len;
+ tmp = tor_malloc(tmplen);
+ memcpy(tmp,s2k_specifier,8);
+ memcpy(tmp+8,secret,secret_len);
+ secret_len += 8;
+ while (count) {
+ if (count >= secret_len) {
+ crypto_digest_add_bytes(d, tmp, secret_len);
+ count -= secret_len;
+ } else {
+ crypto_digest_add_bytes(d, tmp, count);
+ count = 0;
+ }
+ }
+ crypto_digest_get_digest(d, (char*)buf, sizeof(buf));
+
+ if (key_out_len <= sizeof(buf)) {
+ memcpy(key_out, buf, key_out_len);
+ } else {
+ crypto_expand_key_material_rfc5869_sha256(buf, DIGEST_LEN,
+ (const uint8_t*)s2k_specifier, 8,
+ (const uint8_t*)"EXPAND", 6,
+ (uint8_t*)key_out, key_out_len);
+ }
+ memwipe(tmp, 0, tmplen);
+ memwipe(buf, 0, sizeof(buf));
+ tor_free(tmp);
+ crypto_digest_free(d);
+}
+
+/**
+ * Helper: given a valid specifier without prefix type byte in <b>spec</b>,
+ * whose length must be correct, and given a secret passphrase <b>secret</b>
+ * of length <b>secret_len</b>, compute the key and store it into
+ * <b>key_out</b>, which must have enough room for secret_to_key_key_len(type)
+ * bytes. Return the number of bytes written on success and an error code
+ * on failure.
+ */
+STATIC int
+secret_to_key_compute_key(uint8_t *key_out, size_t key_out_len,
+ const uint8_t *spec, size_t spec_len,
+ const char *secret, size_t secret_len,
+ int type)
+{
+ int rv;
+ if (key_out_len > INT_MAX)
+ return S2K_BAD_LEN;
+
+ switch (type) {
+ case S2K_TYPE_RFC2440:
+ secret_to_key_rfc2440((char*)key_out, key_out_len, secret, secret_len,
+ (const char*)spec);
+ return (int)key_out_len;
+
+ case S2K_TYPE_PBKDF2: {
+ uint8_t log_iters;
+ if (spec_len < 1 || secret_len > INT_MAX || spec_len > INT_MAX)
+ return S2K_BAD_LEN;
+ log_iters = spec[spec_len-1];
+ if (log_iters > 31)
+ return S2K_BAD_PARAMS;
+ rv = PKCS5_PBKDF2_HMAC_SHA1(secret, (int)secret_len,
+ spec, (int)spec_len-1,
+ (1<<log_iters),
+ (int)key_out_len, key_out);
+ if (rv < 0)
+ return S2K_FAILED;
+ return (int)key_out_len;
+ }
+
+ case S2K_TYPE_SCRYPT: {
+#ifdef HAVE_SCRYPT
+ uint8_t log_N, log_r, log_p;
+ uint64_t N;
+ uint32_t r, p;
+ if (spec_len < 2)
+ return S2K_BAD_LEN;
+ log_N = spec[spec_len-2];
+ log_r = (spec[spec_len-1]) >> 4;
+ log_p = (spec[spec_len-1]) & 15;
+ if (log_N > 63)
+ return S2K_BAD_PARAMS;
+ N = ((uint64_t)1) << log_N;
+ r = 1u << log_r;
+ p = 1u << log_p;
+ rv = libscrypt_scrypt((const uint8_t*)secret, secret_len,
+ spec, spec_len-2, N, r, p, key_out, key_out_len);
+ if (rv != 0)
+ return S2K_FAILED;
+ return (int)key_out_len;
+#else
+ return S2K_NO_SCRYPT_SUPPORT;
+#endif
+ }
+ default:
+ return S2K_BAD_ALGORITHM;
+ }
+}
+
+/**
+ * Given a specifier previously constructed with secret_to_key_make_specifier
+ * in <b>spec</b> of length <b>spec_len</b>, and a secret password in
+ * <b>secret</b> of length <b>secret_len</b>, generate <b>key_out_len</b>
+ * bytes of cryptographic material in <b>key_out</b>. The native output of
+ * the secret-to-key function will be truncated if key_out_len is short, and
+ * expanded with HKDF if key_out_len is long. Returns S2K_OKAY on success,
+ * and an error code on failure.
+ */
+int
+secret_to_key_derivekey(uint8_t *key_out, size_t key_out_len,
+ const uint8_t *spec, size_t spec_len,
+ const char *secret, size_t secret_len)
+{
+ int legacy_format = 0;
+ int type = secret_to_key_get_type(spec, spec_len, 0, &legacy_format);
+ int r;
+
+ if (type < 0)
+ return type;
+#ifndef HAVE_SCRYPT
+ if (type == S2K_TYPE_SCRYPT)
+ return S2K_NO_SCRYPT_SUPPORT;
+ #endif
+
+ if (! legacy_format) {
+ ++spec;
+ --spec_len;
+ }
+
+ r = secret_to_key_compute_key(key_out, key_out_len, spec, spec_len,
+ secret, secret_len, type);
+ if (r < 0)
+ return r;
+ else
+ return S2K_OKAY;
+}
+
+/**
+ * Construct a new s2k algorithm specifier and salt in <b>buf</b>, according
+ * to the bitwise-or of some S2K_FLAG_* options in <b>flags</b>. Up to
+ * <b>buf_len</b> bytes of storage may be used in <b>buf</b>. Return the
+ * number of bytes used on success and an error code on failure.
+ */
+int
+secret_to_key_make_specifier(uint8_t *buf, size_t buf_len, unsigned flags)
+{
+ int rv;
+ int spec_len;
+#ifdef HAVE_SCRYPT
+ uint8_t type = S2K_TYPE_SCRYPT;
+#else
+ uint8_t type = S2K_TYPE_RFC2440;
+#endif
+
+ if (flags & S2K_FLAG_NO_SCRYPT)
+ type = S2K_TYPE_RFC2440;
+ if (flags & S2K_FLAG_USE_PBKDF2)
+ type = S2K_TYPE_PBKDF2;
+
+ spec_len = secret_to_key_spec_len(type);
+
+ if ((int)buf_len < spec_len + 1)
+ return S2K_TRUNCATED;
+
+ buf[0] = type;
+ rv = make_specifier(buf+1, type, flags);
+ if (rv < 0)
+ return rv;
+ else
+ return rv + 1;
+}
+
+/**
+ * Hash a passphrase from <b>secret</b> of length <b>secret_len</b>, according
+ * to the bitwise-or of some S2K_FLAG_* options in <b>flags</b>, and store the
+ * hash along with salt and hashing parameters into <b>buf</b>. Up to
+ * <b>buf_len</b> bytes of storage may be used in <b>buf</b>. Set
+ * *<b>len_out</b> to the number of bytes used and return S2K_OKAY on success;
+ * and return an error code on failure.
+ */
+int
+secret_to_key_new(uint8_t *buf,
+ size_t buf_len,
+ size_t *len_out,
+ const char *secret, size_t secret_len,
+ unsigned flags)
+{
+ int key_len;
+ int spec_len;
+ int type;
+ int rv;
+
+ spec_len = secret_to_key_make_specifier(buf, buf_len, flags);
+
+ if (spec_len < 0)
+ return spec_len;
+
+ type = buf[0];
+ key_len = secret_to_key_key_len(type);
+
+ if (key_len < 0)
+ return key_len;
+
+ if ((int)buf_len < key_len + spec_len)
+ return S2K_TRUNCATED;
+
+ rv = secret_to_key_compute_key(buf + spec_len, key_len,
+ buf + 1, spec_len-1,
+ secret, secret_len, type);
+ if (rv < 0)
+ return rv;
+
+ *len_out = spec_len + key_len;
+
+ return S2K_OKAY;
+}
+
+/**
+ * Given a hashed passphrase in <b>spec_and_key</b> of length
+ * <b>spec_and_key_len</b> as generated by secret_to_key_new(), verify whether
+ * it is a hash of the passphrase <b>secret</b> of length <b>secret_len</b>.
+ * Return S2K_OKAY on a match, S2K_BAD_SECRET on a well-formed hash that
+ * doesn't match this secret, and another error code on other errors.
+ */
+int
+secret_to_key_check(const uint8_t *spec_and_key, size_t spec_and_key_len,
+ const char *secret, size_t secret_len)
+{
+ int is_legacy = 0;
+ int type = secret_to_key_get_type(spec_and_key, spec_and_key_len,
+ 1, &is_legacy);
+ uint8_t buf[32];
+ int spec_len;
+ int key_len;
+ int rv;
+
+ if (type < 0)
+ return type;
+
+ if (! is_legacy) {
+ spec_and_key++;
+ spec_and_key_len--;
+ }
+
+ spec_len = secret_to_key_spec_len(type);
+ key_len = secret_to_key_key_len(type);
+ tor_assert(spec_len > 0);
+ tor_assert(key_len > 0);
+ tor_assert(key_len <= (int) sizeof(buf));
+ tor_assert((int)spec_and_key_len == spec_len + key_len);
+ rv = secret_to_key_compute_key(buf, key_len,
+ spec_and_key, spec_len,
+ secret, secret_len, type);
+ if (rv < 0)
+ goto done;
+
+ if (tor_memeq(buf, spec_and_key + spec_len, key_len))
+ rv = S2K_OKAY;
+ else
+ rv = S2K_BAD_SECRET;
+
+ done:
+ memwipe(buf, 0, sizeof(buf));
+ return rv;
+}
+
diff --git a/src/common/crypto_s2k.h b/src/common/crypto_s2k.h
new file mode 100644
index 0000000000..3693a430e7
--- /dev/null
+++ b/src/common/crypto_s2k.h
@@ -0,0 +1,73 @@
+/* Copyright (c) 2001, Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2013, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_CRYPTO_S2K_H_INCLUDED
+#define TOR_CRYPTO_S2K_H_INCLUDED
+
+#include <stdio.h>
+#include "torint.h"
+
+/** Length of RFC2440-style S2K specifier: the first 8 bytes are a salt, the
+ * 9th describes how much iteration to do. */
+#define S2K_RFC2440_SPECIFIER_LEN 9
+void secret_to_key_rfc2440(
+ char *key_out, size_t key_out_len, const char *secret,
+ size_t secret_len, const char *s2k_specifier);
+
+/** Flag for secret-to-key function: do not use scrypt. */
+#define S2K_FLAG_NO_SCRYPT (1u<<0)
+/** Flag for secret-to-key functions: if using a memory-tuned s2k function,
+ * assume that we have limited memory. */
+#define S2K_FLAG_LOW_MEM (1u<<1)
+/** Flag for secret-to-key functions: force use of pbkdf2. Without this, we
+ * default to scrypt, then RFC2440. */
+#define S2K_FLAG_USE_PBKDF2 (1u<<2)
+
+/** Maximum possible output length from secret_to_key_new. */
+#define S2K_MAXLEN 64
+
+/** Error code from secret-to-key functions: all is well */
+#define S2K_OKAY 0
+/** Error code from secret-to-key functions: generic failure */
+#define S2K_FAILED -1
+/** Error code from secret-to-key functions: provided secret didn't match */
+#define S2K_BAD_SECRET -2
+/** Error code from secret-to-key functions: didn't recognize the algorithm */
+#define S2K_BAD_ALGORITHM -3
+/** Error code from secret-to-key functions: specifier wasn't valid */
+#define S2K_BAD_PARAMS -4
+/** Error code from secret-to-key functions: compiled without scrypt */
+#define S2K_NO_SCRYPT_SUPPORT -5
+/** Error code from secret-to-key functions: not enough space to write output.
+ */
+#define S2K_TRUNCATED -6
+/** Error code from secret-to-key functions: Wrong length for specifier. */
+#define S2K_BAD_LEN -7
+
+int secret_to_key_new(uint8_t *buf,
+ size_t buf_len,
+ size_t *len_out,
+ const char *secret, size_t secret_len,
+ unsigned flags);
+
+int secret_to_key_make_specifier(uint8_t *buf, size_t buf_len, unsigned flags);
+
+int secret_to_key_check(const uint8_t *spec_and_key, size_t spec_and_key_len,
+ const char *secret, size_t secret_len);
+
+int secret_to_key_derivekey(uint8_t *key_out, size_t key_out_len,
+ const uint8_t *spec, size_t spec_len,
+ const char *secret, size_t secret_len);
+
+#ifdef CRYPTO_S2K_PRIVATE
+STATIC int secret_to_key_compute_key(uint8_t *key_out, size_t key_out_len,
+ const uint8_t *spec, size_t spec_len,
+ const char *secret, size_t secret_len,
+ int type);
+#endif
+
+#endif
+
diff --git a/src/common/include.am b/src/common/include.am
index 68e0110c26..5c000e86f3 100644
--- a/src/common/include.am
+++ b/src/common/include.am
@@ -16,7 +16,7 @@ EXTRA_DIST+= \
src/common/Makefile.nmake
#CFLAGS = -Wall -Wpointer-arith -O2
-AM_CPPFLAGS += -I$(srcdir)/src/common -Isrc/common
+AM_CPPFLAGS += -I$(srcdir)/src/common -Isrc/common -I$(srcdir)/src/ext/trunnel -I$(srcdir)/src/trunnel
if USE_OPENBSD_MALLOC
libor_extra_source=src/ext/OpenBSD_malloc_Linux.c
@@ -52,8 +52,12 @@ LIBDONNA=
endif
endif
+LIBDONNA += $(LIBED25519_REF10)
+
if CURVE25519_ENABLED
-libcrypto_extra_source=src/common/crypto_curve25519.c
+libcrypto_extra_source = \
+ src/common/crypto_curve25519.c \
+ src/common/crypto_ed25519.c
endif
LIBOR_A_SOURCES = \
@@ -69,15 +73,19 @@ LIBOR_A_SOURCES = \
src/common/util_process.c \
src/common/sandbox.c \
src/ext/csiphash.c \
+ src/ext/trunnel/trunnel.c \
$(libor_extra_source) \
$(libor_mempool_source)
LIBOR_CRYPTO_A_SOURCES = \
src/common/aes.c \
src/common/crypto.c \
+ src/common/crypto_pwbox.c \
+ src/common/crypto_s2k.c \
src/common/crypto_format.c \
src/common/torgzip.c \
src/common/tortls.c \
+ src/trunnel/pwbox.c \
$(libcrypto_extra_source)
LIBOR_EVENT_A_SOURCES = \
@@ -110,6 +118,9 @@ COMMONHEADERS = \
src/common/container.h \
src/common/crypto.h \
src/common/crypto_curve25519.h \
+ src/common/crypto_ed25519.h \
+ src/common/crypto_pwbox.h \
+ src/common/crypto_s2k.h \
src/common/di_ops.h \
src/common/memarea.h \
src/common/linux_syscalls.inc \
diff --git a/src/common/sandbox.c b/src/common/sandbox.c
index c7e4dcdf55..36022c921c 100644
--- a/src/common/sandbox.c
+++ b/src/common/sandbox.c
@@ -1297,6 +1297,18 @@ HT_GENERATE2(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
cached_getaddrinfo_items_eq,
0.6, tor_reallocarray_, tor_free_)
+/** If true, don't try to cache getaddrinfo results. */
+static int sandbox_getaddrinfo_cache_disabled = 0;
+
+/** Tell the sandbox layer not to try to cache getaddrinfo results. Used as in
+ * tor-resolve, when we have no intention of initializing crypto or of
+ * installing the sandbox.*/
+void
+sandbox_disable_getaddrinfo_cache(void)
+{
+ sandbox_getaddrinfo_cache_disabled = 1;
+}
+
int
sandbox_getaddrinfo(const char *name, const char *servname,
const struct addrinfo *hints,
@@ -1305,6 +1317,10 @@ sandbox_getaddrinfo(const char *name, const char *servname,
int err;
struct cached_getaddrinfo_item_t search, *item;
+ if (sandbox_getaddrinfo_cache_disabled) {
+ return getaddrinfo(name, NULL, hints, res);
+ }
+
if (servname != NULL) {
log_warn(LD_BUG, "called with non-NULL servname");
return EAI_NONAME;
@@ -1718,5 +1734,10 @@ sandbox_is_active(void)
{
return 0;
}
+
+void
+sandbox_disable_getaddrinfo_cache(void)
+{
+}
#endif
diff --git a/src/common/sandbox.h b/src/common/sandbox.h
index 095d8d47f4..ddb2be5695 100644
--- a/src/common/sandbox.h
+++ b/src/common/sandbox.h
@@ -176,5 +176,7 @@ int sandbox_init(sandbox_cfg_t* cfg);
/** Return true iff the sandbox is turned on. */
int sandbox_is_active(void);
+void sandbox_disable_getaddrinfo_cache(void);
+
#endif /* SANDBOX_H_ */
diff --git a/src/common/tortls.c b/src/common/tortls.c
index eda10bbe2e..b159ae4139 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -1170,6 +1170,9 @@ tor_tls_context_init_one(tor_tls_context_t **ppcontext,
return ((new_ctx != NULL) ? 0 : -1);
}
+/** The group we should use for ecdhe when none was selected. */
+#define NID_tor_default_ecdhe_group NID_X9_62_prime256v1
+
/** Create a new TLS context for use with Tor TLS handshakes.
* <b>identity</b> should be set to the identity key used to sign the
* certificate.
@@ -1240,10 +1243,11 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
goto error;
#endif
- /* Tell OpenSSL to use SSL3 or TLS1 but not SSL2. */
+ /* Tell OpenSSL to use TLS 1.0 or later but not SSL2 or SSL3. */
if (!(result->ctx = SSL_CTX_new(SSLv23_method())))
goto error;
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. */
@@ -1282,6 +1286,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
}
#endif
+ /* XXX This block is now obsolete. */
if (
#ifdef DISABLE_SSL3_HANDSHAKE
1 ||
@@ -1363,7 +1368,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
else if (flags & TOR_TLS_CTX_USE_ECDHE_P256)
nid = NID_X9_62_prime256v1;
else
- nid = NID_X9_62_prime256v1;
+ 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? */
@@ -1463,6 +1468,43 @@ static uint16_t v2_cipher_list[] = {
/** Have we removed the unrecognized ciphers from v2_cipher_list yet? */
static int v2_cipher_list_pruned = 0;
+/** Return 0 if <b>m</b> does not support the cipher with ID <b>cipher</b>;
+ * return 1 if it does support it, or if we have no way to tell. */
+static int
+find_cipher_by_id(const SSL_METHOD *m, uint16_t cipher)
+{
+ const SSL_CIPHER *c;
+#ifdef HAVE_STRUCT_SSL_METHOD_ST_GET_CIPHER_BY_CHAR
+ if (m && m->get_cipher_by_char) {
+ unsigned char cipherid[3];
+ set_uint16(cipherid, 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;
+ } else
+#endif
+ 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;
+ } else {
+ return 1; /* No way to search */
+ }
+}
+
/** 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. */
@@ -1474,16 +1516,7 @@ prune_v2_cipher_list(void)
inp = outp = v2_cipher_list;
while (*inp) {
- unsigned char cipherid[3];
- const SSL_CIPHER *cipher;
- /* Is there no better way to do this? */
- set_uint16(cipherid, htons(*inp));
- 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. */
- cipher = m->get_cipher_by_char(cipherid);
- if (cipher) {
- tor_assert((cipher->id & 0xffff) == *inp);
+ if (find_cipher_by_id(m, *inp)) {
*outp++ = *inp++;
} else {
inp++;
diff --git a/src/common/util.c b/src/common/util.c
index 97cedd519d..ece8aaad81 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -1376,7 +1376,8 @@ n_leapdays(int y1, int y2)
--y2;
return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
}
-/** Number of days per month in non-leap year; used by tor_timegm. */
+/** Number of days per month in non-leap year; used by tor_timegm and
+ * parse_rfc1123_time. */
static const int days_per_month[] =
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
@@ -1390,10 +1391,32 @@ tor_timegm(const struct tm *tm, time_t *time_out)
* It's way more brute-force than fiddling with tzset().
*/
time_t year, days, hours, minutes, seconds;
- int i;
- year = tm->tm_year + 1900;
- if (year < 1970 || tm->tm_mon < 0 || tm->tm_mon > 11 ||
- tm->tm_year >= INT32_MAX-1900) {
+ int i, invalid_year, dpm;
+ /* avoid int overflow on addition */
+ if (tm->tm_year < INT32_MAX-1900) {
+ year = tm->tm_year + 1900;
+ } else {
+ /* clamp year */
+ year = INT32_MAX;
+ }
+ invalid_year = (year < 1970 || tm->tm_year >= INT32_MAX-1900);
+
+ if (tm->tm_mon >= 0 && tm->tm_mon <= 11) {
+ dpm = days_per_month[tm->tm_mon];
+ if (tm->tm_mon == 1 && !invalid_year && IS_LEAPYEAR(tm->tm_year)) {
+ dpm = 29;
+ }
+ } else {
+ /* invalid month - default to 0 days per month */
+ dpm = 0;
+ }
+
+ if (invalid_year ||
+ tm->tm_mon < 0 || tm->tm_mon > 11 ||
+ tm->tm_mday < 1 || tm->tm_mday > dpm ||
+ tm->tm_hour < 0 || tm->tm_hour > 23 ||
+ tm->tm_min < 0 || tm->tm_min > 59 ||
+ tm->tm_sec < 0 || tm->tm_sec > 60) {
log_warn(LD_BUG, "Out-of-range argument to tor_timegm");
return -1;
}
@@ -1457,8 +1480,9 @@ parse_rfc1123_time(const char *buf, time_t *t)
struct tm tm;
char month[4];
char weekday[4];
- int i, m;
+ int i, m, invalid_year;
unsigned tm_mday, tm_year, tm_hour, tm_min, tm_sec;
+ unsigned dpm;
if (strlen(buf) != RFC1123_TIME_LEN)
return -1;
@@ -1471,18 +1495,6 @@ parse_rfc1123_time(const char *buf, time_t *t)
tor_free(esc);
return -1;
}
- if (tm_mday < 1 || tm_mday > 31 || tm_hour > 23 || tm_min > 59 ||
- tm_sec > 60 || tm_year >= INT32_MAX || tm_year < 1970) {
- char *esc = esc_for_log(buf);
- log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc);
- tor_free(esc);
- return -1;
- }
- tm.tm_mday = (int)tm_mday;
- tm.tm_year = (int)tm_year;
- tm.tm_hour = (int)tm_hour;
- tm.tm_min = (int)tm_min;
- tm.tm_sec = (int)tm_sec;
m = -1;
for (i = 0; i < 12; ++i) {
@@ -1499,6 +1511,26 @@ parse_rfc1123_time(const char *buf, time_t *t)
}
tm.tm_mon = m;
+ invalid_year = (tm_year >= INT32_MAX || tm_year < 1970);
+ tor_assert(m >= 0 && m <= 11);
+ dpm = days_per_month[m];
+ if (m == 1 && !invalid_year && IS_LEAPYEAR(tm_year)) {
+ dpm = 29;
+ }
+
+ if (invalid_year || tm_mday < 1 || tm_mday > dpm ||
+ tm_hour > 23 || tm_min > 59 || tm_sec > 60) {
+ char *esc = esc_for_log(buf);
+ log_warn(LD_GENERAL, "Got invalid RFC1123 time %s", esc);
+ tor_free(esc);
+ return -1;
+ }
+ tm.tm_mday = (int)tm_mday;
+ tm.tm_year = (int)tm_year;
+ tm.tm_hour = (int)tm_hour;
+ tm.tm_min = (int)tm_min;
+ tm.tm_sec = (int)tm_sec;
+
if (tm.tm_year < 1970) {
char *esc = esc_for_log(buf);
log_warn(LD_GENERAL,
@@ -1670,7 +1702,11 @@ format_time_interval(char *out, size_t out_len, long interval)
{
/* We only report seconds if there's no hours. */
long sec = 0, min = 0, hour = 0, day = 0;
- if (interval < 0)
+
+ /* -LONG_MIN is LONG_MAX + 1, which causes signed overflow */
+ if (interval < -LONG_MAX)
+ interval = LONG_MAX;
+ else if (interval < 0)
interval = -interval;
if (interval >= 86400) {
@@ -2837,10 +2873,14 @@ scan_unsigned(const char **bufp, unsigned long *out, int width, int base)
while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp))
&& scanned_so_far < width) {
int digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++);
- unsigned long new_result = result * base + digit;
- if (new_result < result)
- return -1; /* over/underflow. */
- result = new_result;
+ // Check for overflow beforehand, without actually causing any overflow
+ // This preserves functionality on compilers that don't wrap overflow
+ // (i.e. that trap or optimise away overflow)
+ // result * base + digit > ULONG_MAX
+ // result * base > ULONG_MAX - digit
+ if (result > (ULONG_MAX - digit)/base)
+ return -1; /* Processing this digit would overflow */
+ result = result * base + digit;
++scanned_so_far;
}
@@ -2875,10 +2915,17 @@ scan_signed(const char **bufp, long *out, int width)
if (scan_unsigned(bufp, &result, width, 10) < 0)
return -1;
- if (neg) {
+ if (neg && result > 0) {
if (result > ((unsigned long)LONG_MAX) + 1)
return -1; /* Underflow */
- *out = -(long)result;
+ // Avoid overflow on the cast to signed long when result is LONG_MIN
+ // by subtracting 1 from the unsigned long positive value,
+ // then, after it has been cast to signed and negated,
+ // subtracting the original 1 (the double-subtraction is intentional).
+ // Otherwise, the cast to signed could cause a temporary long
+ // to equal LONG_MAX + 1, which is undefined.
+ // We avoid underflow on the subtraction by treating -0 as positive.
+ *out = (-(long)(result - 1)) - 1;
} else {
if (result > LONG_MAX)
return -1; /* Overflow */
@@ -3577,7 +3624,13 @@ format_helper_exit_status(unsigned char child_state, int saved_errno,
/* Convert errno to be unsigned for hex conversion */
if (saved_errno < 0) {
- unsigned_errno = (unsigned int) -saved_errno;
+ // Avoid overflow on the cast to unsigned int when result is INT_MIN
+ // by adding 1 to the signed int negative value,
+ // then, after it has been negated and cast to unsigned,
+ // adding the original 1 back (the double-addition is intentional).
+ // Otherwise, the cast to signed could cause a temporary int
+ // to equal INT_MAX + 1, which is undefined.
+ unsigned_errno = ((unsigned int) -(saved_errno + 1)) + 1;
} else {
unsigned_errno = (unsigned int) saved_errno;
}
diff --git a/src/config/include.am b/src/config/include.am
index 35961b829a..c283628513 100644
--- a/src/config/include.am
+++ b/src/config/include.am
@@ -2,7 +2,7 @@ confdir = $(sysconfdir)/tor
tordatadir = $(datadir)/tor
-EXTRA_DIST+= src/config/geoip src/config/geoip6
+EXTRA_DIST+= src/config/geoip src/config/geoip6 src/config/torrc.minimal.in
# fallback-consensus
conf_DATA = src/config/torrc.sample
diff --git a/src/config/torrc.minimal.in b/src/config/torrc.minimal.in
new file mode 100644
index 0000000000..d842fbcaf5
--- /dev/null
+++ b/src/config/torrc.minimal.in
@@ -0,0 +1,192 @@
+## Configuration file for a typical Tor user
+## Last updated 9 October 2013 for Tor 0.2.5.2-alpha.
+## (may or may not work for much older or much newer versions of Tor.)
+##
+## Lines that begin with "## " try to explain what's going on. Lines
+## that begin with just "#" are disabled commands: you can enable them
+## by removing the "#" symbol.
+##
+## See 'man tor', or https://www.torproject.org/docs/tor-manual.html,
+## for more options you can use in this file.
+##
+## Tor will look for this file in various places based on your platform:
+## https://www.torproject.org/docs/faq#torrc
+
+## Tor opens a socks proxy on port 9050 by default -- even if you don't
+## configure one below. Set "SocksPort 0" if you plan to run Tor only
+## as a relay, and not make any local application connections yourself.
+#SocksPort 9050 # Default: Bind to localhost:9050 for local connections.
+#SocksPort 192.168.0.1:9100 # Bind to this address:port too.
+
+## Entry policies to allow/deny SOCKS requests based on IP address.
+## First entry that matches wins. If no SocksPolicy is set, we accept
+## all (and only) requests that reach a SocksPort. Untrusted users who
+## can access your SocksPort may be able to learn about the connections
+## you make.
+#SocksPolicy accept 192.168.0.0/16
+#SocksPolicy reject *
+
+## Logs go to stdout at level "notice" unless redirected by something
+## else, like one of the below lines. You can have as many Log lines as
+## you want.
+##
+## We advise using "notice" in most cases, since anything more verbose
+## may provide sensitive information to an attacker who obtains the logs.
+##
+## Send all messages of level 'notice' or higher to @LOCALSTATEDIR@/log/tor/notices.log
+#Log notice file @LOCALSTATEDIR@/log/tor/notices.log
+## Send every possible message to @LOCALSTATEDIR@/log/tor/debug.log
+#Log debug file @LOCALSTATEDIR@/log/tor/debug.log
+## Use the system log instead of Tor's logfiles
+#Log notice syslog
+## To send all messages to stderr:
+#Log debug stderr
+
+## Uncomment this to start the process in the background... or use
+## --runasdaemon 1 on the command line. This is ignored on Windows;
+## see the FAQ entry if you want Tor to run as an NT service.
+#RunAsDaemon 1
+
+## The directory for keeping all the keys/etc. By default, we store
+## things in $HOME/.tor on Unix, and in Application Data\tor on Windows.
+#DataDirectory @LOCALSTATEDIR@/lib/tor
+
+## The port on which Tor will listen for local connections from Tor
+## controller applications, as documented in control-spec.txt.
+#ControlPort 9051
+## If you enable the controlport, be sure to enable one of these
+## authentication methods, to prevent attackers from accessing it.
+#HashedControlPassword 16:872860B76453A77D60CA2BB8C1A7042072093276A3D701AD684053EC4C
+#CookieAuthentication 1
+
+############### This section is just for location-hidden services ###
+
+## Once you have configured a hidden service, you can look at the
+## contents of the file ".../hidden_service/hostname" for the address
+## to tell people.
+##
+## HiddenServicePort x y:z says to redirect requests on port x to the
+## address y:z.
+
+#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/hidden_service/
+#HiddenServicePort 80 127.0.0.1:80
+
+#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/other_hidden_service/
+#HiddenServicePort 80 127.0.0.1:80
+#HiddenServicePort 22 127.0.0.1:22
+
+################ This section is just for relays #####################
+#
+## See https://www.torproject.org/docs/tor-doc-relay for details.
+
+## Required: what port to advertise for incoming Tor connections.
+#ORPort 9001
+## If you want to listen on a port other than the one advertised in
+## ORPort (e.g. to advertise 443 but bind to 9090), you can do it as
+## follows. You'll need to do ipchains or other port forwarding
+## yourself to make this work.
+#ORPort 443 NoListen
+#ORPort 127.0.0.1:9090 NoAdvertise
+
+## The IP address or full DNS name for incoming connections to your
+## relay. Leave commented out and Tor will guess.
+#Address noname.example.com
+
+## If you have multiple network interfaces, you can specify one for
+## outgoing traffic to use.
+# OutboundBindAddress 10.0.0.5
+
+## A handle for your relay, so people don't have to refer to it by key.
+#Nickname ididnteditheconfig
+
+## Define these to limit how much relayed traffic you will allow. Your
+## own traffic is still unthrottled. Note that RelayBandwidthRate must
+## be at least 20 KB.
+## Note that units for these config options are bytes per second, not bits
+## per second, and that prefixes are binary prefixes, i.e. 2^10, 2^20, etc.
+#RelayBandwidthRate 100 KB # Throttle traffic to 100KB/s (800Kbps)
+#RelayBandwidthBurst 200 KB # But allow bursts up to 200KB/s (1600Kbps)
+
+## Use these to restrict the maximum traffic per day, week, or month.
+## Note that this threshold applies separately to sent and received bytes,
+## not to their sum: setting "4 GB" may allow up to 8 GB total before
+## hibernating.
+##
+## Set a maximum of 4 gigabytes each way per period.
+#AccountingMax 4 GB
+## Each period starts daily at midnight (AccountingMax is per day)
+#AccountingStart day 00:00
+## Each period starts on the 3rd of the month at 15:00 (AccountingMax
+## is per month)
+#AccountingStart month 3 15:00
+
+## Administrative contact information for this relay or bridge. This line
+## can be used to contact you if your relay or bridge is misconfigured or
+## something else goes wrong. Note that we archive and publish all
+## descriptors containing these lines and that Google indexes them, so
+## spammers might also collect them. You may want to obscure the fact that
+## it's an email address and/or generate a new address for this purpose.
+#ContactInfo Random Person <nobody AT example dot com>
+## You might also include your PGP or GPG fingerprint if you have one:
+#ContactInfo 0xFFFFFFFF Random Person <nobody AT example dot com>
+
+## Uncomment this to mirror directory information for others. Please do
+## if you have enough bandwidth.
+#DirPort 9030 # what port to advertise for directory connections
+## If you want to listen on a port other than the one advertised in
+## DirPort (e.g. to advertise 80 but bind to 9091), you can do it as
+## follows. below too. You'll need to do ipchains or other port
+## forwarding yourself to make this work.
+#DirPort 80 NoListen
+#DirPort 127.0.0.1:9091 NoAdvertise
+## Uncomment to return an arbitrary blob of html on your DirPort. Now you
+## can explain what Tor is if anybody wonders why your IP address is
+## contacting them. See contrib/tor-exit-notice.html in Tor's source
+## distribution for a sample.
+#DirPortFrontPage @CONFDIR@/tor-exit-notice.html
+
+## Uncomment this if you run more than one Tor relay, and add the identity
+## key fingerprint of each Tor relay you control, even if they're on
+## different networks. You declare it here so Tor clients can avoid
+## using more than one of your relays in a single circuit. See
+## https://www.torproject.org/docs/faq#MultipleRelays
+## However, you should never include a bridge's fingerprint here, as it would
+## break its concealability and potentionally reveal its IP/TCP address.
+#MyFamily $keyid,$keyid,...
+
+## A comma-separated list of exit policies. They're considered first
+## to last, and the first match wins. If you want to _replace_
+## the default exit policy, end this with either a reject *:* or an
+## accept *:*. Otherwise, you're _augmenting_ (prepending to) the
+## default exit policy. Leave commented to just use the default, which is
+## described in the man page or at
+## https://www.torproject.org/documentation.html
+##
+## Look at https://www.torproject.org/faq-abuse.html#TypicalAbuses
+## for issues you might encounter if you use the default exit policy.
+##
+## If certain IPs and ports are blocked externally, e.g. by your firewall,
+## you should update your exit policy to reflect this -- otherwise Tor
+## users will be told that those destinations are down.
+##
+## For security, by default Tor rejects connections to private (local)
+## networks, including to your public IP address. See the man page entry
+## for ExitPolicyRejectPrivate if you want to allow "exit enclaving".
+##
+#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports but no more
+#ExitPolicy accept *:119 # accept nntp as well as default exit policy
+#ExitPolicy reject *:* # no exits allowed
+
+## Bridge relays (or "bridges") are Tor relays that aren't listed in the
+## main directory. Since there is no complete public list of them, even an
+## ISP that filters connections to all the known Tor relays probably
+## won't be able to block all the bridges. Also, websites won't treat you
+## differently because they won't know you're running Tor. If you can
+## be a real relay, please do; but if not, be a bridge!
+#BridgeRelay 1
+## By default, Tor will advertise your bridge to users through various
+## mechanisms like https://bridges.torproject.org/. If you want to run
+## a private bridge, for example because you'll give out your bridge
+## address manually to your friends, uncomment this line:
+#PublishServerDescriptor 0
+
diff --git a/src/config/torrc.minimal.in-staging b/src/config/torrc.minimal.in-staging
new file mode 100644
index 0000000000..bde800fd23
--- /dev/null
+++ b/src/config/torrc.minimal.in-staging
@@ -0,0 +1,193 @@
+## Configuration file for a typical Tor user
+## Last updated 2 September 2014 for Tor 0.2.6.1-alpha.
+## (may or may not work for much older or much newer versions of Tor.)
+##
+## Lines that begin with "## " try to explain what's going on. Lines
+## that begin with just "#" are disabled commands: you can enable them
+## by removing the "#" symbol.
+##
+## See 'man tor', or https://www.torproject.org/docs/tor-manual.html,
+## for more options you can use in this file.
+##
+## Tor will look for this file in various places based on your platform:
+## https://www.torproject.org/docs/faq#torrc
+
+## Tor opens a socks proxy on port 9050 by default -- even if you don't
+## configure one below. Set "SocksPort 0" if you plan to run Tor only
+## as a relay, and not make any local application connections yourself.
+#SocksPort 9050 # Default: Bind to localhost:9050 for local connections.
+#SocksPort 192.168.0.1:9100 # Bind to this address:port too.
+
+## Entry policies to allow/deny SOCKS requests based on IP address.
+## First entry that matches wins. If no SocksPolicy is set, we accept
+## all (and only) requests that reach a SocksPort. Untrusted users who
+## can access your SocksPort may be able to learn about the connections
+## you make.
+#SocksPolicy accept 192.168.0.0/16
+#SocksPolicy reject *
+
+## Logs go to stdout at level "notice" unless redirected by something
+## else, like one of the below lines. You can have as many Log lines as
+## you want.
+##
+## We advise using "notice" in most cases, since anything more verbose
+## may provide sensitive information to an attacker who obtains the logs.
+##
+## Send all messages of level 'notice' or higher to @LOCALSTATEDIR@/log/tor/notices.log
+#Log notice file @LOCALSTATEDIR@/log/tor/notices.log
+## Send every possible message to @LOCALSTATEDIR@/log/tor/debug.log
+#Log debug file @LOCALSTATEDIR@/log/tor/debug.log
+## Use the system log instead of Tor's logfiles
+#Log notice syslog
+## To send all messages to stderr:
+#Log debug stderr
+
+## Uncomment this to start the process in the background... or use
+## --runasdaemon 1 on the command line. This is ignored on Windows;
+## see the FAQ entry if you want Tor to run as an NT service.
+#RunAsDaemon 1
+
+## The directory for keeping all the keys/etc. By default, we store
+## things in $HOME/.tor on Unix, and in Application Data\tor on Windows.
+#DataDirectory @LOCALSTATEDIR@/lib/tor
+
+## The port on which Tor will listen for local connections from Tor
+## controller applications, as documented in control-spec.txt.
+#ControlPort 9051
+## If you enable the controlport, be sure to enable one of these
+## authentication methods, to prevent attackers from accessing it.
+#HashedControlPassword 16:872860B76453A77D60CA2BB8C1A7042072093276A3D701AD684053EC4C
+#CookieAuthentication 1
+
+############### This section is just for location-hidden services ###
+
+## Once you have configured a hidden service, you can look at the
+## contents of the file ".../hidden_service/hostname" for the address
+## to tell people.
+##
+## HiddenServicePort x y:z says to redirect requests on port x to the
+## address y:z.
+
+#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/hidden_service/
+#HiddenServicePort 80 127.0.0.1:80
+
+#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/other_hidden_service/
+#HiddenServicePort 80 127.0.0.1:80
+#HiddenServicePort 22 127.0.0.1:22
+
+################ This section is just for relays #####################
+#
+## See https://www.torproject.org/docs/tor-doc-relay for details.
+
+## Required: what port to advertise for incoming Tor connections.
+#ORPort 9001
+## If you want to listen on a port other than the one advertised in
+## ORPort (e.g. to advertise 443 but bind to 9090), you can do it as
+## follows. You'll need to do ipchains or other port forwarding
+## yourself to make this work.
+#ORPort 443 NoListen
+#ORPort 127.0.0.1:9090 NoAdvertise
+
+## The IP address or full DNS name for incoming connections to your
+## relay. Leave commented out and Tor will guess.
+#Address noname.example.com
+
+## If you have multiple network interfaces, you can specify one for
+## outgoing traffic to use.
+# OutboundBindAddress 10.0.0.5
+
+## A handle for your relay, so people don't have to refer to it by key.
+#Nickname ididnteditheconfig
+
+## Define these to limit how much relayed traffic you will allow. Your
+## own traffic is still unthrottled. Note that RelayBandwidthRate must
+## be at least 20 kilobytes per second.
+## Note that units for these config options are bytes (per second), not
+## bits (per second), and that prefixes are binary prefixes, i.e. 2^10,
+## 2^20, etc.
+#RelayBandwidthRate 100 KBytes # Throttle traffic to 100KB/s (800Kbps)
+#RelayBandwidthBurst 200 KBytes # But allow bursts up to 200KB (1600Kb)
+
+## Use these to restrict the maximum traffic per day, week, or month.
+## Note that this threshold applies separately to sent and received bytes,
+## not to their sum: setting "4 GB" may allow up to 8 GB total before
+## hibernating.
+##
+## Set a maximum of 4 gigabytes each way per period.
+#AccountingMax 4 GBytes
+## Each period starts daily at midnight (AccountingMax is per day)
+#AccountingStart day 00:00
+## Each period starts on the 3rd of the month at 15:00 (AccountingMax
+## is per month)
+#AccountingStart month 3 15:00
+
+## Administrative contact information for this relay or bridge. This line
+## can be used to contact you if your relay or bridge is misconfigured or
+## something else goes wrong. Note that we archive and publish all
+## descriptors containing these lines and that Google indexes them, so
+## spammers might also collect them. You may want to obscure the fact that
+## it's an email address and/or generate a new address for this purpose.
+#ContactInfo Random Person <nobody AT example dot com>
+## You might also include your PGP or GPG fingerprint if you have one:
+#ContactInfo 0xFFFFFFFF Random Person <nobody AT example dot com>
+
+## Uncomment this to mirror directory information for others. Please do
+## if you have enough bandwidth.
+#DirPort 9030 # what port to advertise for directory connections
+## If you want to listen on a port other than the one advertised in
+## DirPort (e.g. to advertise 80 but bind to 9091), you can do it as
+## follows. below too. You'll need to do ipchains or other port
+## forwarding yourself to make this work.
+#DirPort 80 NoListen
+#DirPort 127.0.0.1:9091 NoAdvertise
+## Uncomment to return an arbitrary blob of html on your DirPort. Now you
+## can explain what Tor is if anybody wonders why your IP address is
+## contacting them. See contrib/tor-exit-notice.html in Tor's source
+## distribution for a sample.
+#DirPortFrontPage @CONFDIR@/tor-exit-notice.html
+
+## Uncomment this if you run more than one Tor relay, and add the identity
+## key fingerprint of each Tor relay you control, even if they're on
+## different networks. You declare it here so Tor clients can avoid
+## using more than one of your relays in a single circuit. See
+## https://www.torproject.org/docs/faq#MultipleRelays
+## However, you should never include a bridge's fingerprint here, as it would
+## break its concealability and potentially reveal its IP/TCP address.
+#MyFamily $keyid,$keyid,...
+
+## A comma-separated list of exit policies. They're considered first
+## to last, and the first match wins. If you want to _replace_
+## the default exit policy, end this with either a reject *:* or an
+## accept *:*. Otherwise, you're _augmenting_ (prepending to) the
+## default exit policy. Leave commented to just use the default, which is
+## described in the man page or at
+## https://www.torproject.org/documentation.html
+##
+## Look at https://www.torproject.org/faq-abuse.html#TypicalAbuses
+## for issues you might encounter if you use the default exit policy.
+##
+## If certain IPs and ports are blocked externally, e.g. by your firewall,
+## you should update your exit policy to reflect this -- otherwise Tor
+## users will be told that those destinations are down.
+##
+## For security, by default Tor rejects connections to private (local)
+## networks, including to your public IP address. See the man page entry
+## for ExitPolicyRejectPrivate if you want to allow "exit enclaving".
+##
+#ExitPolicy accept *:6660-6667,reject *:* # allow irc ports but no more
+#ExitPolicy accept *:119 # accept nntp as well as default exit policy
+#ExitPolicy reject *:* # no exits allowed
+
+## Bridge relays (or "bridges") are Tor relays that aren't listed in the
+## main directory. Since there is no complete public list of them, even an
+## ISP that filters connections to all the known Tor relays probably
+## won't be able to block all the bridges. Also, websites won't treat you
+## differently because they won't know you're running Tor. If you can
+## be a real relay, please do; but if not, be a bridge!
+#BridgeRelay 1
+## By default, Tor will advertise your bridge to users through various
+## mechanisms like https://bridges.torproject.org/. If you want to run
+## a private bridge, for example because you'll give out your bridge
+## address manually to your friends, uncomment this line:
+#PublishServerDescriptor 0
+
diff --git a/src/config/torrc.sample.in b/src/config/torrc.sample.in
index d842fbcaf5..bde800fd23 100644
--- a/src/config/torrc.sample.in
+++ b/src/config/torrc.sample.in
@@ -1,5 +1,5 @@
## Configuration file for a typical Tor user
-## Last updated 9 October 2013 for Tor 0.2.5.2-alpha.
+## Last updated 2 September 2014 for Tor 0.2.6.1-alpha.
## (may or may not work for much older or much newer versions of Tor.)
##
## Lines that begin with "## " try to explain what's going on. Lines
@@ -101,11 +101,12 @@
## Define these to limit how much relayed traffic you will allow. Your
## own traffic is still unthrottled. Note that RelayBandwidthRate must
-## be at least 20 KB.
-## Note that units for these config options are bytes per second, not bits
-## per second, and that prefixes are binary prefixes, i.e. 2^10, 2^20, etc.
-#RelayBandwidthRate 100 KB # Throttle traffic to 100KB/s (800Kbps)
-#RelayBandwidthBurst 200 KB # But allow bursts up to 200KB/s (1600Kbps)
+## be at least 20 kilobytes per second.
+## Note that units for these config options are bytes (per second), not
+## bits (per second), and that prefixes are binary prefixes, i.e. 2^10,
+## 2^20, etc.
+#RelayBandwidthRate 100 KBytes # Throttle traffic to 100KB/s (800Kbps)
+#RelayBandwidthBurst 200 KBytes # But allow bursts up to 200KB (1600Kb)
## Use these to restrict the maximum traffic per day, week, or month.
## Note that this threshold applies separately to sent and received bytes,
@@ -113,7 +114,7 @@
## hibernating.
##
## Set a maximum of 4 gigabytes each way per period.
-#AccountingMax 4 GB
+#AccountingMax 4 GBytes
## Each period starts daily at midnight (AccountingMax is per day)
#AccountingStart day 00:00
## Each period starts on the 3rd of the month at 15:00 (AccountingMax
@@ -151,7 +152,7 @@
## using more than one of your relays in a single circuit. See
## https://www.torproject.org/docs/faq#MultipleRelays
## However, you should never include a bridge's fingerprint here, as it would
-## break its concealability and potentionally reveal its IP/TCP address.
+## break its concealability and potentially reveal its IP/TCP address.
#MyFamily $keyid,$keyid,...
## A comma-separated list of exit policies. They're considered first
diff --git a/src/ext/README b/src/ext/README
index 5d5a6e1518..616716e099 100644
--- a/src/ext/README
+++ b/src/ext/README
@@ -49,3 +49,15 @@ siphash.h
Marek Majkowski's implementation of siphash 2-4, a secure keyed
hash algorithm to avoid collision-based DoS attacks against hash
tables.
+
+trunnel/*.[ch]
+
+ Headers and runtime code for Trunnel, a system for generating
+ code to encode and decode binary formats.
+
+ed25519/ref10/*
+
+ Daniel Bernsten's portable ref10 implementation of ed25519.
+ Public domain.
+
+
diff --git a/src/ext/ed25519/ref10/Makefile b/src/ext/ed25519/ref10/Makefile
new file mode 100644
index 0000000000..9b0ba7ad45
--- /dev/null
+++ b/src/ext/ed25519/ref10/Makefile
@@ -0,0 +1,41 @@
+all: d.h d2.h sqrtm1.h base.h base2.h \
+ge_add.h ge_sub.h \
+ge_madd.h ge_msub.h \
+ge_p2_dbl.h \
+pow225521.h pow22523.h
+
+d.h: d.py
+ python d.py > d.h
+
+d2.h: d2.py
+ python d2.py > d2.h
+
+sqrtm1.h: sqrtm1.py
+ python sqrtm1.py > sqrtm1.h
+
+base.h: base.py
+ python base.py > base.h
+
+base2.h: base2.py
+ python base2.py > base2.h
+
+ge_add.h: ge_add.q q2h.sh
+ ./q2h.sh < ge_add.q > ge_add.h
+
+ge_sub.h: ge_sub.q q2h.sh
+ ./q2h.sh < ge_sub.q > ge_sub.h
+
+ge_madd.h: ge_madd.q q2h.sh
+ ./q2h.sh < ge_madd.q > ge_madd.h
+
+ge_msub.h: ge_msub.q q2h.sh
+ ./q2h.sh < ge_msub.q > ge_msub.h
+
+ge_p2_dbl.h: ge_p2_dbl.q q2h.sh
+ ./q2h.sh < ge_p2_dbl.q > ge_p2_dbl.h
+
+pow22523.h: pow22523.q q2h.sh
+ ./q2h.sh < pow22523.q > pow22523.h
+
+pow225521.h: pow225521.q q2h.sh
+ ./q2h.sh < pow225521.q > pow225521.h
diff --git a/src/ext/ed25519/ref10/README.tor b/src/ext/ed25519/ref10/README.tor
new file mode 100644
index 0000000000..38ed97ba05
--- /dev/null
+++ b/src/ext/ed25519/ref10/README.tor
@@ -0,0 +1,23 @@
+
+We've made the following changes to the stock ed25519_ref10 from
+supercop-20140622:
+
+ * We added the necessary glue to provide integers of fixed bit
+ sizes, SHA512, and to compile without warnings everywhere we need
+ to build.
+
+ * Secret keys are stored in expanded format. There are functions
+ to expand them from the 32-byte seed.
+
+ * Signatures are made and processed detached from the messages that
+ they sign. (In other words, we support "make signature" and
+ "check signature", not "create signed message" and "check and
+ unpack signed message".)
+
+ * There's an implementation of 'convert a curve25519 key to an
+ ed25519 key' so we can do cross-certification with curve25519 keys.
+ (keyconv.c)
+
+ * There's an implementation of multiplicative key blinding so we
+ can use it for next-gen hidden srevice descriptors. (blinding.c)
+
diff --git a/src/ext/ed25519/ref10/api.h b/src/ext/ed25519/ref10/api.h
new file mode 100644
index 0000000000..d88dae0c32
--- /dev/null
+++ b/src/ext/ed25519/ref10/api.h
@@ -0,0 +1,4 @@
+#define CRYPTO_SECRETKEYBYTES 64
+#define CRYPTO_PUBLICKEYBYTES 32
+#define CRYPTO_BYTES 64
+#define CRYPTO_DETERMINISTIC 1
diff --git a/src/ext/ed25519/ref10/base.h b/src/ext/ed25519/ref10/base.h
new file mode 100644
index 0000000000..573bd8a05c
--- /dev/null
+++ b/src/ext/ed25519/ref10/base.h
@@ -0,0 +1,1344 @@
+{
+ {
+ { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 },
+ { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 },
+ { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 },
+ },
+ {
+ { -12815894,-12976347,-21581243,11784320,-25355658,-2750717,-11717903,-3814571,-358445,-10211303 },
+ { -21703237,6903825,27185491,6451973,-29577724,-9554005,-15616551,11189268,-26829678,-5319081 },
+ { 26966642,11152617,32442495,15396054,14353839,-12752335,-3128826,-9541118,-15472047,-4166697 },
+ },
+ {
+ { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 },
+ { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 },
+ { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 },
+ },
+ {
+ { -17036878,13921892,10945806,-6033431,27105052,-16084379,-28926210,15006023,3284568,-6276540 },
+ { 23599295,-8306047,-11193664,-7687416,13236774,10506355,7464579,9656445,13059162,10374397 },
+ { 7798556,16710257,3033922,2874086,28997861,2835604,32406664,-3839045,-641708,-101325 },
+ },
+ {
+ { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 },
+ { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 },
+ { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 },
+ },
+ {
+ { -15371964,-12862754,32573250,4720197,-26436522,5875511,-19188627,-15224819,-9818940,-12085777 },
+ { -8549212,109983,15149363,2178705,22900618,4543417,3044240,-15689887,1762328,14866737 },
+ { -18199695,-15951423,-10473290,1707278,-17185920,3916101,-28236412,3959421,27914454,4383652 },
+ },
+ {
+ { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 },
+ { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 },
+ { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 },
+ },
+ {
+ { 14499471,-2729599,-33191113,-4254652,28494862,14271267,30290735,10876454,-33154098,2381726 },
+ { -7195431,-2655363,-14730155,462251,-27724326,3941372,-6236617,3696005,-32300832,15351955 },
+ { 27431194,8222322,16448760,-3907995,-18707002,11938355,-32961401,-2970515,29551813,10109425 },
+ },
+},
+{
+ {
+ { -13657040,-13155431,-31283750,11777098,21447386,6519384,-2378284,-1627556,10092783,-4764171 },
+ { 27939166,14210322,4677035,16277044,-22964462,-12398139,-32508754,12005538,-17810127,12803510 },
+ { 17228999,-15661624,-1233527,300140,-1224870,-11714777,30364213,-9038194,18016357,4397660 },
+ },
+ {
+ { -10958843,-7690207,4776341,-14954238,27850028,-15602212,-26619106,14544525,-17477504,982639 },
+ { 29253598,15796703,-2863982,-9908884,10057023,3163536,7332899,-4120128,-21047696,9934963 },
+ { 5793303,16271923,-24131614,-10116404,29188560,1206517,-14747930,4559895,-30123922,-10897950 },
+ },
+ {
+ { -27643952,-11493006,16282657,-11036493,28414021,-15012264,24191034,4541697,-13338309,5500568 },
+ { 12650548,-1497113,9052871,11355358,-17680037,-8400164,-17430592,12264343,10874051,13524335 },
+ { 25556948,-3045990,714651,2510400,23394682,-10415330,33119038,5080568,-22528059,5376628 },
+ },
+ {
+ { -26088264,-4011052,-17013699,-3537628,-6726793,1920897,-22321305,-9447443,4535768,1569007 },
+ { -2255422,14606630,-21692440,-8039818,28430649,8775819,-30494562,3044290,31848280,12543772 },
+ { -22028579,2943893,-31857513,6777306,13784462,-4292203,-27377195,-2062731,7718482,14474653 },
+ },
+ {
+ { 2385315,2454213,-22631320,46603,-4437935,-15680415,656965,-7236665,24316168,-5253567 },
+ { 13741529,10911568,-33233417,-8603737,-20177830,-1033297,33040651,-13424532,-20729456,8321686 },
+ { 21060490,-2212744,15712757,-4336099,1639040,10656336,23845965,-11874838,-9984458,608372 },
+ },
+ {
+ { -13672732,-15087586,-10889693,-7557059,-6036909,11305547,1123968,-6780577,27229399,23887 },
+ { -23244140,-294205,-11744728,14712571,-29465699,-2029617,12797024,-6440308,-1633405,16678954 },
+ { -29500620,4770662,-16054387,14001338,7830047,9564805,-1508144,-4795045,-17169265,4904953 },
+ },
+ {
+ { 24059557,14617003,19037157,-15039908,19766093,-14906429,5169211,16191880,2128236,-4326833 },
+ { -16981152,4124966,-8540610,-10653797,30336522,-14105247,-29806336,916033,-6882542,-2986532 },
+ { -22630907,12419372,-7134229,-7473371,-16478904,16739175,285431,2763829,15736322,4143876 },
+ },
+ {
+ { 2379352,11839345,-4110402,-5988665,11274298,794957,212801,-14594663,23527084,-16458268 },
+ { 33431127,-11130478,-17838966,-15626900,8909499,8376530,-32625340,4087881,-15188911,-14416214 },
+ { 1767683,7197987,-13205226,-2022635,-13091350,448826,5799055,4357868,-4774191,-16323038 },
+ },
+},
+{
+ {
+ { 6721966,13833823,-23523388,-1551314,26354293,-11863321,23365147,-3949732,7390890,2759800 },
+ { 4409041,2052381,23373853,10530217,7676779,-12885954,21302353,-4264057,1244380,-12919645 },
+ { -4421239,7169619,4982368,-2957590,30256825,-2777540,14086413,9208236,15886429,16489664 },
+ },
+ {
+ { 1996075,10375649,14346367,13311202,-6874135,-16438411,-13693198,398369,-30606455,-712933 },
+ { -25307465,9795880,-2777414,14878809,-33531835,14780363,13348553,12076947,-30836462,5113182 },
+ { -17770784,11797796,31950843,13929123,-25888302,12288344,-30341101,-7336386,13847711,5387222 },
+ },
+ {
+ { -18582163,-3416217,17824843,-2340966,22744343,-10442611,8763061,3617786,-19600662,10370991 },
+ { 20246567,-14369378,22358229,-543712,18507283,-10413996,14554437,-8746092,32232924,16763880 },
+ { 9648505,10094563,26416693,14745928,-30374318,-6472621,11094161,15689506,3140038,-16510092 },
+ },
+ {
+ { -16160072,5472695,31895588,4744994,8823515,10365685,-27224800,9448613,-28774454,366295 },
+ { 19153450,11523972,-11096490,-6503142,-24647631,5420647,28344573,8041113,719605,11671788 },
+ { 8678025,2694440,-6808014,2517372,4964326,11152271,-15432916,-15266516,27000813,-10195553 },
+ },
+ {
+ { -15157904,7134312,8639287,-2814877,-7235688,10421742,564065,5336097,6750977,-14521026 },
+ { 11836410,-3979488,26297894,16080799,23455045,15735944,1695823,-8819122,8169720,16220347 },
+ { -18115838,8653647,17578566,-6092619,-8025777,-16012763,-11144307,-2627664,-5990708,-14166033 },
+ },
+ {
+ { -23308498,-10968312,15213228,-10081214,-30853605,-11050004,27884329,2847284,2655861,1738395 },
+ { -27537433,-14253021,-25336301,-8002780,-9370762,8129821,21651608,-3239336,-19087449,-11005278 },
+ { 1533110,3437855,23735889,459276,29970501,11335377,26030092,5821408,10478196,8544890 },
+ },
+ {
+ { 32173121,-16129311,24896207,3921497,22579056,-3410854,19270449,12217473,17789017,-3395995 },
+ { -30552961,-2228401,-15578829,-10147201,13243889,517024,15479401,-3853233,30460520,1052596 },
+ { -11614875,13323618,32618793,8175907,-15230173,12596687,27491595,-4612359,3179268,-9478891 },
+ },
+ {
+ { 31947069,-14366651,-4640583,-15339921,-15125977,-6039709,-14756777,-16411740,19072640,-9511060 },
+ { 11685058,11822410,3158003,-13952594,33402194,-4165066,5977896,-5215017,473099,5040608 },
+ { -20290863,8198642,-27410132,11602123,1290375,-2799760,28326862,1721092,-19558642,-3131606 },
+ },
+},
+{
+ {
+ { 7881532,10687937,7578723,7738378,-18951012,-2553952,21820786,8076149,-27868496,11538389 },
+ { -19935666,3899861,18283497,-6801568,-15728660,-11249211,8754525,7446702,-5676054,5797016 },
+ { -11295600,-3793569,-15782110,-7964573,12708869,-8456199,2014099,-9050574,-2369172,-5877341 },
+ },
+ {
+ { -22472376,-11568741,-27682020,1146375,18956691,16640559,1192730,-3714199,15123619,10811505 },
+ { 14352098,-3419715,-18942044,10822655,32750596,4699007,-70363,15776356,-28886779,-11974553 },
+ { -28241164,-8072475,-4978962,-5315317,29416931,1847569,-20654173,-16484855,4714547,-9600655 },
+ },
+ {
+ { 15200332,8368572,19679101,15970074,-31872674,1959451,24611599,-4543832,-11745876,12340220 },
+ { 12876937,-10480056,33134381,6590940,-6307776,14872440,9613953,8241152,15370987,9608631 },
+ { -4143277,-12014408,8446281,-391603,4407738,13629032,-7724868,15866074,-28210621,-8814099 },
+ },
+ {
+ { 26660628,-15677655,8393734,358047,-7401291,992988,-23904233,858697,20571223,8420556 },
+ { 14620715,13067227,-15447274,8264467,14106269,15080814,33531827,12516406,-21574435,-12476749 },
+ { 236881,10476226,57258,-14677024,6472998,2466984,17258519,7256740,8791136,15069930 },
+ },
+ {
+ { 1276410,-9371918,22949635,-16322807,-23493039,-5702186,14711875,4874229,-30663140,-2331391 },
+ { 5855666,4990204,-13711848,7294284,-7804282,1924647,-1423175,-7912378,-33069337,9234253 },
+ { 20590503,-9018988,31529744,-7352666,-2706834,10650548,31559055,-11609587,18979186,13396066 },
+ },
+ {
+ { 24474287,4968103,22267082,4407354,24063882,-8325180,-18816887,13594782,33514650,7021958 },
+ { -11566906,-6565505,-21365085,15928892,-26158305,4315421,-25948728,-3916677,-21480480,12868082 },
+ { -28635013,13504661,19988037,-2132761,21078225,6443208,-21446107,2244500,-12455797,-8089383 },
+ },
+ {
+ { -30595528,13793479,-5852820,319136,-25723172,-6263899,33086546,8957937,-15233648,5540521 },
+ { -11630176,-11503902,-8119500,-7643073,2620056,1022908,-23710744,-1568984,-16128528,-14962807 },
+ { 23152971,775386,27395463,14006635,-9701118,4649512,1689819,892185,-11513277,-15205948 },
+ },
+ {
+ { 9770129,9586738,26496094,4324120,1556511,-3550024,27453819,4763127,-19179614,5867134 },
+ { -32765025,1927590,31726409,-4753295,23962434,-16019500,27846559,5931263,-29749703,-16108455 },
+ { 27461885,-2977536,22380810,1815854,-23033753,-3031938,7283490,-15148073,-19526700,7734629 },
+ },
+},
+{
+ {
+ { -8010264,-9590817,-11120403,6196038,29344158,-13430885,7585295,-3176626,18549497,15302069 },
+ { -32658337,-6171222,-7672793,-11051681,6258878,13504381,10458790,-6418461,-8872242,8424746 },
+ { 24687205,8613276,-30667046,-3233545,1863892,-1830544,19206234,7134917,-11284482,-828919 },
+ },
+ {
+ { 11334899,-9218022,8025293,12707519,17523892,-10476071,10243738,-14685461,-5066034,16498837 },
+ { 8911542,6887158,-9584260,-6958590,11145641,-9543680,17303925,-14124238,6536641,10543906 },
+ { -28946384,15479763,-17466835,568876,-1497683,11223454,-2669190,-16625574,-27235709,8876771 },
+ },
+ {
+ { -25742899,-12566864,-15649966,-846607,-33026686,-796288,-33481822,15824474,-604426,-9039817 },
+ { 10330056,70051,7957388,-9002667,9764902,15609756,27698697,-4890037,1657394,3084098 },
+ { 10477963,-7470260,12119566,-13250805,29016247,-5365589,31280319,14396151,-30233575,15272409 },
+ },
+ {
+ { -12288309,3169463,28813183,16658753,25116432,-5630466,-25173957,-12636138,-25014757,1950504 },
+ { -26180358,9489187,11053416,-14746161,-31053720,5825630,-8384306,-8767532,15341279,8373727 },
+ { 28685821,7759505,-14378516,-12002860,-31971820,4079242,298136,-10232602,-2878207,15190420 },
+ },
+ {
+ { -32932876,13806336,-14337485,-15794431,-24004620,10940928,8669718,2742393,-26033313,-6875003 },
+ { -1580388,-11729417,-25979658,-11445023,-17411874,-10912854,9291594,-16247779,-12154742,6048605 },
+ { -30305315,14843444,1539301,11864366,20201677,1900163,13934231,5128323,11213262,9168384 },
+ },
+ {
+ { -26280513,11007847,19408960,-940758,-18592965,-4328580,-5088060,-11105150,20470157,-16398701 },
+ { -23136053,9282192,14855179,-15390078,-7362815,-14408560,-22783952,14461608,14042978,5230683 },
+ { 29969567,-2741594,-16711867,-8552442,9175486,-2468974,21556951,3506042,-5933891,-12449708 },
+ },
+ {
+ { -3144746,8744661,19704003,4581278,-20430686,6830683,-21284170,8971513,-28539189,15326563 },
+ { -19464629,10110288,-17262528,-3503892,-23500387,1355669,-15523050,15300988,-20514118,9168260 },
+ { -5353335,4488613,-23803248,16314347,7780487,-15638939,-28948358,9601605,33087103,-9011387 },
+ },
+ {
+ { -19443170,-15512900,-20797467,-12445323,-29824447,10229461,-27444329,-15000531,-5996870,15664672 },
+ { 23294591,-16632613,-22650781,-8470978,27844204,11461195,13099750,-2460356,18151676,13417686 },
+ { -24722913,-4176517,-31150679,5988919,-26858785,6685065,1661597,-12551441,15271676,-15452665 },
+ },
+},
+{
+ {
+ { 11433042,-13228665,8239631,-5279517,-1985436,-725718,-18698764,2167544,-6921301,-13440182 },
+ { -31436171,15575146,30436815,12192228,-22463353,9395379,-9917708,-8638997,12215110,12028277 },
+ { 14098400,6555944,23007258,5757252,-15427832,-12950502,30123440,4617780,-16900089,-655628 },
+ },
+ {
+ { -4026201,-15240835,11893168,13718664,-14809462,1847385,-15819999,10154009,23973261,-12684474 },
+ { -26531820,-3695990,-1908898,2534301,-31870557,-16550355,18341390,-11419951,32013174,-10103539 },
+ { -25479301,10876443,-11771086,-14625140,-12369567,1838104,21911214,6354752,4425632,-837822 },
+ },
+ {
+ { -10433389,-14612966,22229858,-3091047,-13191166,776729,-17415375,-12020462,4725005,14044970 },
+ { 19268650,-7304421,1555349,8692754,-21474059,-9910664,6347390,-1411784,-19522291,-16109756 },
+ { -24864089,12986008,-10898878,-5558584,-11312371,-148526,19541418,8180106,9282262,10282508 },
+ },
+ {
+ { -26205082,4428547,-8661196,-13194263,4098402,-14165257,15522535,8372215,5542595,-10702683 },
+ { -10562541,14895633,26814552,-16673850,-17480754,-2489360,-2781891,6993761,-18093885,10114655 },
+ { -20107055,-929418,31422704,10427861,-7110749,6150669,-29091755,-11529146,25953725,-106158 },
+ },
+ {
+ { -4234397,-8039292,-9119125,3046000,2101609,-12607294,19390020,6094296,-3315279,12831125 },
+ { -15998678,7578152,5310217,14408357,-33548620,-224739,31575954,6326196,7381791,-2421839 },
+ { -20902779,3296811,24736065,-16328389,18374254,7318640,6295303,8082724,-15362489,12339664 },
+ },
+ {
+ { 27724736,2291157,6088201,-14184798,1792727,5857634,13848414,15768922,25091167,14856294 },
+ { -18866652,8331043,24373479,8541013,-701998,-9269457,12927300,-12695493,-22182473,-9012899 },
+ { -11423429,-5421590,11632845,3405020,30536730,-11674039,-27260765,13866390,30146206,9142070 },
+ },
+ {
+ { 3924129,-15307516,-13817122,-10054960,12291820,-668366,-27702774,9326384,-8237858,4171294 },
+ { -15921940,16037937,6713787,16606682,-21612135,2790944,26396185,3731949,345228,-5462949 },
+ { -21327538,13448259,25284571,1143661,20614966,-8849387,2031539,-12391231,-16253183,-13582083 },
+ },
+ {
+ { 31016211,-16722429,26371392,-14451233,-5027349,14854137,17477601,3842657,28012650,-16405420 },
+ { -5075835,9368966,-8562079,-4600902,-15249953,6970560,-9189873,16292057,-8867157,3507940 },
+ { 29439664,3537914,23333589,6997794,-17555561,-11018068,-15209202,-15051267,-9164929,6580396 },
+ },
+},
+{
+ {
+ { -12185861,-7679788,16438269,10826160,-8696817,-6235611,17860444,-9273846,-2095802,9304567 },
+ { 20714564,-4336911,29088195,7406487,11426967,-5095705,14792667,-14608617,5289421,-477127 },
+ { -16665533,-10650790,-6160345,-13305760,9192020,-1802462,17271490,12349094,26939669,-3752294 },
+ },
+ {
+ { -12889898,9373458,31595848,16374215,21471720,13221525,-27283495,-12348559,-3698806,117887 },
+ { 22263325,-6560050,3984570,-11174646,-15114008,-566785,28311253,5358056,-23319780,541964 },
+ { 16259219,3261970,2309254,-15534474,-16885711,-4581916,24134070,-16705829,-13337066,-13552195 },
+ },
+ {
+ { 9378160,-13140186,-22845982,-12745264,28198281,-7244098,-2399684,-717351,690426,14876244 },
+ { 24977353,-314384,-8223969,-13465086,28432343,-1176353,-13068804,-12297348,-22380984,6618999 },
+ { -1538174,11685646,12944378,13682314,-24389511,-14413193,8044829,-13817328,32239829,-5652762 },
+ },
+ {
+ { -18603066,4762990,-926250,8885304,-28412480,-3187315,9781647,-10350059,32779359,5095274 },
+ { -33008130,-5214506,-32264887,-3685216,9460461,-9327423,-24601656,14506724,21639561,-2630236 },
+ { -16400943,-13112215,25239338,15531969,3987758,-4499318,-1289502,-6863535,17874574,558605 },
+ },
+ {
+ { -13600129,10240081,9171883,16131053,-20869254,9599700,33499487,5080151,2085892,5119761 },
+ { -22205145,-2519528,-16381601,414691,-25019550,2170430,30634760,-8363614,-31999993,-5759884 },
+ { -6845704,15791202,8550074,-1312654,29928809,-12092256,27534430,-7192145,-22351378,12961482 },
+ },
+ {
+ { -24492060,-9570771,10368194,11582341,-23397293,-2245287,16533930,8206996,-30194652,-5159638 },
+ { -11121496,-3382234,2307366,6362031,-135455,8868177,-16835630,7031275,7589640,8945490 },
+ { -32152748,8917967,6661220,-11677616,-1192060,-15793393,7251489,-11182180,24099109,-14456170 },
+ },
+ {
+ { 5019558,-7907470,4244127,-14714356,-26933272,6453165,-19118182,-13289025,-6231896,-10280736 },
+ { 10853594,10721687,26480089,5861829,-22995819,1972175,-1866647,-10557898,-3363451,-6441124 },
+ { -17002408,5906790,221599,-6563147,7828208,-13248918,24362661,-2008168,-13866408,7421392 },
+ },
+ {
+ { 8139927,-6546497,32257646,-5890546,30375719,1886181,-21175108,15441252,28826358,-4123029 },
+ { 6267086,9695052,7709135,-16603597,-32869068,-1886135,14795160,-7840124,13746021,-1742048 },
+ { 28584902,7787108,-6732942,-15050729,22846041,-7571236,-3181936,-363524,4771362,-8419958 },
+ },
+},
+{
+ {
+ { 24949256,6376279,-27466481,-8174608,-18646154,-9930606,33543569,-12141695,3569627,11342593 },
+ { 26514989,4740088,27912651,3697550,19331575,-11472339,6809886,4608608,7325975,-14801071 },
+ { -11618399,-14554430,-24321212,7655128,-1369274,5214312,-27400540,10258390,-17646694,-8186692 },
+ },
+ {
+ { 11431204,15823007,26570245,14329124,18029990,4796082,-31446179,15580664,9280358,-3973687 },
+ { -160783,-10326257,-22855316,-4304997,-20861367,-13621002,-32810901,-11181622,-15545091,4387441 },
+ { -20799378,12194512,3937617,-5805892,-27154820,9340370,-24513992,8548137,20617071,-7482001 },
+ },
+ {
+ { -938825,-3930586,-8714311,16124718,24603125,-6225393,-13775352,-11875822,24345683,10325460 },
+ { -19855277,-1568885,-22202708,8714034,14007766,6928528,16318175,-1010689,4766743,3552007 },
+ { -21751364,-16730916,1351763,-803421,-4009670,3950935,3217514,14481909,10988822,-3994762 },
+ },
+ {
+ { 15564307,-14311570,3101243,5684148,30446780,-8051356,12677127,-6505343,-8295852,13296005 },
+ { -9442290,6624296,-30298964,-11913677,-4670981,-2057379,31521204,9614054,-30000824,12074674 },
+ { 4771191,-135239,14290749,-13089852,27992298,14998318,-1413936,-1556716,29832613,-16391035 },
+ },
+ {
+ { 7064884,-7541174,-19161962,-5067537,-18891269,-2912736,25825242,5293297,-27122660,13101590 },
+ { -2298563,2439670,-7466610,1719965,-27267541,-16328445,32512469,-5317593,-30356070,-4190957 },
+ { -30006540,10162316,-33180176,3981723,-16482138,-13070044,14413974,9515896,19568978,9628812 },
+ },
+ {
+ { 33053803,199357,15894591,1583059,27380243,-4580435,-17838894,-6106839,-6291786,3437740 },
+ { -18978877,3884493,19469877,12726490,15913552,13614290,-22961733,70104,7463304,4176122 },
+ { -27124001,10659917,11482427,-16070381,12771467,-6635117,-32719404,-5322751,24216882,5944158 },
+ },
+ {
+ { 8894125,7450974,-2664149,-9765752,-28080517,-12389115,19345746,14680796,11632993,5847885 },
+ { 26942781,-2315317,9129564,-4906607,26024105,11769399,-11518837,6367194,-9727230,4782140 },
+ { 19916461,-4828410,-22910704,-11414391,25606324,-5972441,33253853,8220911,6358847,-1873857 },
+ },
+ {
+ { 801428,-2081702,16569428,11065167,29875704,96627,7908388,-4480480,-13538503,1387155 },
+ { 19646058,5720633,-11416706,12814209,11607948,12749789,14147075,15156355,-21866831,11835260 },
+ { 19299512,1155910,28703737,14890794,2925026,7269399,26121523,15467869,-26560550,5052483 },
+ },
+},
+{
+ {
+ { -3017432,10058206,1980837,3964243,22160966,12322533,-6431123,-12618185,12228557,-7003677 },
+ { 32944382,14922211,-22844894,5188528,21913450,-8719943,4001465,13238564,-6114803,8653815 },
+ { 22865569,-4652735,27603668,-12545395,14348958,8234005,24808405,5719875,28483275,2841751 },
+ },
+ {
+ { -16420968,-1113305,-327719,-12107856,21886282,-15552774,-1887966,-315658,19932058,-12739203 },
+ { -11656086,10087521,-8864888,-5536143,-19278573,-3055912,3999228,13239134,-4777469,-13910208 },
+ { 1382174,-11694719,17266790,9194690,-13324356,9720081,20403944,11284705,-14013818,3093230 },
+ },
+ {
+ { 16650921,-11037932,-1064178,1570629,-8329746,7352753,-302424,16271225,-24049421,-6691850 },
+ { -21911077,-5927941,-4611316,-5560156,-31744103,-10785293,24123614,15193618,-21652117,-16739389 },
+ { -9935934,-4289447,-25279823,4372842,2087473,10399484,31870908,14690798,17361620,11864968 },
+ },
+ {
+ { -11307610,6210372,13206574,5806320,-29017692,-13967200,-12331205,-7486601,-25578460,-16240689 },
+ { 14668462,-12270235,26039039,15305210,25515617,4542480,10453892,6577524,9145645,-6443880 },
+ { 5974874,3053895,-9433049,-10385191,-31865124,3225009,-7972642,3936128,-5652273,-3050304 },
+ },
+ {
+ { 30625386,-4729400,-25555961,-12792866,-20484575,7695099,17097188,-16303496,-27999779,1803632 },
+ { -3553091,9865099,-5228566,4272701,-5673832,-16689700,14911344,12196514,-21405489,7047412 },
+ { 20093277,9920966,-11138194,-5343857,13161587,12044805,-32856851,4124601,-32343828,-10257566 },
+ },
+ {
+ { -20788824,14084654,-13531713,7842147,19119038,-13822605,4752377,-8714640,-21679658,2288038 },
+ { -26819236,-3283715,29965059,3039786,-14473765,2540457,29457502,14625692,-24819617,12570232 },
+ { -1063558,-11551823,16920318,12494842,1278292,-5869109,-21159943,-3498680,-11974704,4724943 },
+ },
+ {
+ { 17960970,-11775534,-4140968,-9702530,-8876562,-1410617,-12907383,-8659932,-29576300,1903856 },
+ { 23134274,-14279132,-10681997,-1611936,20684485,15770816,-12989750,3190296,26955097,14109738 },
+ { 15308788,5320727,-30113809,-14318877,22902008,7767164,29425325,-11277562,31960942,11934971 },
+ },
+ {
+ { -27395711,8435796,4109644,12222639,-24627868,14818669,20638173,4875028,10491392,1379718 },
+ { -13159415,9197841,3875503,-8936108,-1383712,-5879801,33518459,16176658,21432314,12180697 },
+ { -11787308,11500838,13787581,-13832590,-22430679,10140205,1465425,12689540,-10301319,-13872883 },
+ },
+},
+{
+ {
+ { 5414091,-15386041,-21007664,9643570,12834970,1186149,-2622916,-1342231,26128231,6032912 },
+ { -26337395,-13766162,32496025,-13653919,17847801,-12669156,3604025,8316894,-25875034,-10437358 },
+ { 3296484,6223048,24680646,-12246460,-23052020,5903205,-8862297,-4639164,12376617,3188849 },
+ },
+ {
+ { 29190488,-14659046,27549113,-1183516,3520066,-10697301,32049515,-7309113,-16109234,-9852307 },
+ { -14744486,-9309156,735818,-598978,-20407687,-5057904,25246078,-15795669,18640741,-960977 },
+ { -6928835,-16430795,10361374,5642961,4910474,12345252,-31638386,-494430,10530747,1053335 },
+ },
+ {
+ { -29265967,-14186805,-13538216,-12117373,-19457059,-10655384,-31462369,-2948985,24018831,15026644 },
+ { -22592535,-3145277,-2289276,5953843,-13440189,9425631,25310643,13003497,-2314791,-15145616 },
+ { -27419985,-603321,-8043984,-1669117,-26092265,13987819,-27297622,187899,-23166419,-2531735 },
+ },
+ {
+ { -21744398,-13810475,1844840,5021428,-10434399,-15911473,9716667,16266922,-5070217,726099 },
+ { 29370922,-6053998,7334071,-15342259,9385287,2247707,-13661962,-4839461,30007388,-15823341 },
+ { -936379,16086691,23751945,-543318,-1167538,-5189036,9137109,730663,9835848,4555336 },
+ },
+ {
+ { -23376435,1410446,-22253753,-12899614,30867635,15826977,17693930,544696,-11985298,12422646 },
+ { 31117226,-12215734,-13502838,6561947,-9876867,-12757670,-5118685,-4096706,29120153,13924425 },
+ { -17400879,-14233209,19675799,-2734756,-11006962,-5858820,-9383939,-11317700,7240931,-237388 },
+ },
+ {
+ { -31361739,-11346780,-15007447,-5856218,-22453340,-12152771,1222336,4389483,3293637,-15551743 },
+ { -16684801,-14444245,11038544,11054958,-13801175,-3338533,-24319580,7733547,12796905,-6335822 },
+ { -8759414,-10817836,-25418864,10783769,-30615557,-9746811,-28253339,3647836,3222231,-11160462 },
+ },
+ {
+ { 18606113,1693100,-25448386,-15170272,4112353,10045021,23603893,-2048234,-7550776,2484985 },
+ { 9255317,-3131197,-12156162,-1004256,13098013,-9214866,16377220,-2102812,-19802075,-3034702 },
+ { -22729289,7496160,-5742199,11329249,19991973,-3347502,-31718148,9936966,-30097688,-10618797 },
+ },
+ {
+ { 21878590,-5001297,4338336,13643897,-3036865,13160960,19708896,5415497,-7360503,-4109293 },
+ { 27736861,10103576,12500508,8502413,-3413016,-9633558,10436918,-1550276,-23659143,-8132100 },
+ { 19492550,-12104365,-29681976,-852630,-3208171,12403437,30066266,8367329,13243957,8709688 },
+ },
+},
+{
+ {
+ { 12015105,2801261,28198131,10151021,24818120,-4743133,-11194191,-5645734,5150968,7274186 },
+ { 2831366,-12492146,1478975,6122054,23825128,-12733586,31097299,6083058,31021603,-9793610 },
+ { -2529932,-2229646,445613,10720828,-13849527,-11505937,-23507731,16354465,15067285,-14147707 },
+ },
+ {
+ { 7840942,14037873,-33364863,15934016,-728213,-3642706,21403988,1057586,-19379462,-12403220 },
+ { 915865,-16469274,15608285,-8789130,-24357026,6060030,-17371319,8410997,-7220461,16527025 },
+ { 32922597,-556987,20336074,-16184568,10903705,-5384487,16957574,52992,23834301,6588044 },
+ },
+ {
+ { 32752030,11232950,3381995,-8714866,22652988,-10744103,17159699,16689107,-20314580,-1305992 },
+ { -4689649,9166776,-25710296,-10847306,11576752,12733943,7924251,-2752281,1976123,-7249027 },
+ { 21251222,16309901,-2983015,-6783122,30810597,12967303,156041,-3371252,12331345,-8237197 },
+ },
+ {
+ { 8651614,-4477032,-16085636,-4996994,13002507,2950805,29054427,-5106970,10008136,-4667901 },
+ { 31486080,15114593,-14261250,12951354,14369431,-7387845,16347321,-13662089,8684155,-10532952 },
+ { 19443825,11385320,24468943,-9659068,-23919258,2187569,-26263207,-6086921,31316348,14219878 },
+ },
+ {
+ { -28594490,1193785,32245219,11392485,31092169,15722801,27146014,6992409,29126555,9207390 },
+ { 32382935,1110093,18477781,11028262,-27411763,-7548111,-4980517,10843782,-7957600,-14435730 },
+ { 2814918,7836403,27519878,-7868156,-20894015,-11553689,-21494559,8550130,28346258,1994730 },
+ },
+ {
+ { -19578299,8085545,-14000519,-3948622,2785838,-16231307,-19516951,7174894,22628102,8115180 },
+ { -30405132,955511,-11133838,-15078069,-32447087,-13278079,-25651578,3317160,-9943017,930272 },
+ { -15303681,-6833769,28856490,1357446,23421993,1057177,24091212,-1388970,-22765376,-10650715 },
+ },
+ {
+ { -22751231,-5303997,-12907607,-12768866,-15811511,-7797053,-14839018,-16554220,-1867018,8398970 },
+ { -31969310,2106403,-4736360,1362501,12813763,16200670,22981545,-6291273,18009408,-15772772 },
+ { -17220923,-9545221,-27784654,14166835,29815394,7444469,29551787,-3727419,19288549,1325865 },
+ },
+ {
+ { 15100157,-15835752,-23923978,-1005098,-26450192,15509408,12376730,-3479146,33166107,-8042750 },
+ { 20909231,13023121,-9209752,16251778,-5778415,-8094914,12412151,10018715,2213263,-13878373 },
+ { 32529814,-11074689,30361439,-16689753,-9135940,1513226,22922121,6382134,-5766928,8371348 },
+ },
+},
+{
+ {
+ { 9923462,11271500,12616794,3544722,-29998368,-1721626,12891687,-8193132,-26442943,10486144 },
+ { -22597207,-7012665,8587003,-8257861,4084309,-12970062,361726,2610596,-23921530,-11455195 },
+ { 5408411,-1136691,-4969122,10561668,24145918,14240566,31319731,-4235541,19985175,-3436086 },
+ },
+ {
+ { -13994457,16616821,14549246,3341099,32155958,13648976,-17577068,8849297,65030,8370684 },
+ { -8320926,-12049626,31204563,5839400,-20627288,-1057277,-19442942,6922164,12743482,-9800518 },
+ { -2361371,12678785,28815050,4759974,-23893047,4884717,23783145,11038569,18800704,255233 },
+ },
+ {
+ { -5269658,-1773886,13957886,7990715,23132995,728773,13393847,9066957,19258688,-14753793 },
+ { -2936654,-10827535,-10432089,14516793,-3640786,4372541,-31934921,2209390,-1524053,2055794 },
+ { 580882,16705327,5468415,-2683018,-30926419,-14696000,-7203346,-8994389,-30021019,7394435 },
+ },
+ {
+ { 23838809,1822728,-15738443,15242727,8318092,-3733104,-21672180,-3492205,-4821741,14799921 },
+ { 13345610,9759151,3371034,-16137791,16353039,8577942,31129804,13496856,-9056018,7402518 },
+ { 2286874,-4435931,-20042458,-2008336,-13696227,5038122,11006906,-15760352,8205061,1607563 },
+ },
+ {
+ { 14414086,-8002132,3331830,-3208217,22249151,-5594188,18364661,-2906958,30019587,-9029278 },
+ { -27688051,1585953,-10775053,931069,-29120221,-11002319,-14410829,12029093,9944378,8024 },
+ { 4368715,-3709630,29874200,-15022983,-20230386,-11410704,-16114594,-999085,-8142388,5640030 },
+ },
+ {
+ { 10299610,13746483,11661824,16234854,7630238,5998374,9809887,-16694564,15219798,-14327783 },
+ { 27425505,-5719081,3055006,10660664,23458024,595578,-15398605,-1173195,-18342183,9742717 },
+ { 6744077,2427284,26042789,2720740,-847906,1118974,32324614,7406442,12420155,1994844 },
+ },
+ {
+ { 14012521,-5024720,-18384453,-9578469,-26485342,-3936439,-13033478,-10909803,24319929,-6446333 },
+ { 16412690,-4507367,10772641,15929391,-17068788,-4658621,10555945,-10484049,-30102368,-4739048 },
+ { 22397382,-7767684,-9293161,-12792868,17166287,-9755136,-27333065,6199366,21880021,-12250760 },
+ },
+ {
+ { -4283307,5368523,-31117018,8163389,-30323063,3209128,16557151,8890729,8840445,4957760 },
+ { -15447727,709327,-6919446,-10870178,-29777922,6522332,-21720181,12130072,-14796503,5005757 },
+ { -2114751,-14308128,23019042,15765735,-25269683,6002752,10183197,-13239326,-16395286,-2176112 },
+ },
+},
+{
+ {
+ { -19025756,1632005,13466291,-7995100,-23640451,16573537,-32013908,-3057104,22208662,2000468 },
+ { 3065073,-1412761,-25598674,-361432,-17683065,-5703415,-8164212,11248527,-3691214,-7414184 },
+ { 10379208,-6045554,8877319,1473647,-29291284,-12507580,16690915,2553332,-3132688,16400289 },
+ },
+ {
+ { 15716668,1254266,-18472690,7446274,-8448918,6344164,-22097271,-7285580,26894937,9132066 },
+ { 24158887,12938817,11085297,-8177598,-28063478,-4457083,-30576463,64452,-6817084,-2692882 },
+ { 13488534,7794716,22236231,5989356,25426474,-12578208,2350710,-3418511,-4688006,2364226 },
+ },
+ {
+ { 16335052,9132434,25640582,6678888,1725628,8517937,-11807024,-11697457,15445875,-7798101 },
+ { 29004207,-7867081,28661402,-640412,-12794003,-7943086,31863255,-4135540,-278050,-15759279 },
+ { -6122061,-14866665,-28614905,14569919,-10857999,-3591829,10343412,-6976290,-29828287,-10815811 },
+ },
+ {
+ { 27081650,3463984,14099042,-4517604,1616303,-6205604,29542636,15372179,17293797,960709 },
+ { 20263915,11434237,-5765435,11236810,13505955,-10857102,-16111345,6493122,-19384511,7639714 },
+ { -2830798,-14839232,25403038,-8215196,-8317012,-16173699,18006287,-16043750,29994677,-15808121 },
+ },
+ {
+ { 9769828,5202651,-24157398,-13631392,-28051003,-11561624,-24613141,-13860782,-31184575,709464 },
+ { 12286395,13076066,-21775189,-1176622,-25003198,4057652,-32018128,-8890874,16102007,13205847 },
+ { 13733362,5599946,10557076,3195751,-5557991,8536970,-25540170,8525972,10151379,10394400 },
+ },
+ {
+ { 4024660,-16137551,22436262,12276534,-9099015,-2686099,19698229,11743039,-33302334,8934414 },
+ { -15879800,-4525240,-8580747,-2934061,14634845,-698278,-9449077,3137094,-11536886,11721158 },
+ { 17555939,-5013938,8268606,2331751,-22738815,9761013,9319229,8835153,-9205489,-1280045 },
+ },
+ {
+ { -461409,-7830014,20614118,16688288,-7514766,-4807119,22300304,505429,6108462,-6183415 },
+ { -5070281,12367917,-30663534,3234473,32617080,-8422642,29880583,-13483331,-26898490,-7867459 },
+ { -31975283,5726539,26934134,10237677,-3173717,-605053,24199304,3795095,7592688,-14992079 },
+ },
+ {
+ { 21594432,-14964228,17466408,-4077222,32537084,2739898,6407723,12018833,-28256052,4298412 },
+ { -20650503,-11961496,-27236275,570498,3767144,-1717540,13891942,-1569194,13717174,10805743 },
+ { -14676630,-15644296,15287174,11927123,24177847,-8175568,-796431,14860609,-26938930,-5863836 },
+ },
+},
+{
+ {
+ { 12962541,5311799,-10060768,11658280,18855286,-7954201,13286263,-12808704,-4381056,9882022 },
+ { 18512079,11319350,-20123124,15090309,18818594,5271736,-22727904,3666879,-23967430,-3299429 },
+ { -6789020,-3146043,16192429,13241070,15898607,-14206114,-10084880,-6661110,-2403099,5276065 },
+ },
+ {
+ { 30169808,-5317648,26306206,-11750859,27814964,7069267,7152851,3684982,1449224,13082861 },
+ { 10342826,3098505,2119311,193222,25702612,12233820,23697382,15056736,-21016438,-8202000 },
+ { -33150110,3261608,22745853,7948688,19370557,-15177665,-26171976,6482814,-10300080,-11060101 },
+ },
+ {
+ { 32869458,-5408545,25609743,15678670,-10687769,-15471071,26112421,2521008,-22664288,6904815 },
+ { 29506923,4457497,3377935,-9796444,-30510046,12935080,1561737,3841096,-29003639,-6657642 },
+ { 10340844,-6630377,-18656632,-2278430,12621151,-13339055,30878497,-11824370,-25584551,5181966 },
+ },
+ {
+ { 25940115,-12658025,17324188,-10307374,-8671468,15029094,24396252,-16450922,-2322852,-12388574 },
+ { -21765684,9916823,-1300409,4079498,-1028346,11909559,1782390,12641087,20603771,-6561742 },
+ { -18882287,-11673380,24849422,11501709,13161720,-4768874,1925523,11914390,4662781,7820689 },
+ },
+ {
+ { 12241050,-425982,8132691,9393934,32846760,-1599620,29749456,12172924,16136752,15264020 },
+ { -10349955,-14680563,-8211979,2330220,-17662549,-14545780,10658213,6671822,19012087,3772772 },
+ { 3753511,-3421066,10617074,2028709,14841030,-6721664,28718732,-15762884,20527771,12988982 },
+ },
+ {
+ { -14822485,-5797269,-3707987,12689773,-898983,-10914866,-24183046,-10564943,3299665,-12424953 },
+ { -16777703,-15253301,-9642417,4978983,3308785,8755439,6943197,6461331,-25583147,8991218 },
+ { -17226263,1816362,-1673288,-6086439,31783888,-8175991,-32948145,7417950,-30242287,1507265 },
+ },
+ {
+ { 29692663,6829891,-10498800,4334896,20945975,-11906496,-28887608,8209391,14606362,-10647073 },
+ { -3481570,8707081,32188102,5672294,22096700,1711240,-33020695,9761487,4170404,-2085325 },
+ { -11587470,14855945,-4127778,-1531857,-26649089,15084046,22186522,16002000,-14276837,-8400798 },
+ },
+ {
+ { -4811456,13761029,-31703877,-2483919,-3312471,7869047,-7113572,-9620092,13240845,10965870 },
+ { -7742563,-8256762,-14768334,-13656260,-23232383,12387166,4498947,14147411,29514390,4302863 },
+ { -13413405,-12407859,20757302,-13801832,14785143,8976368,-5061276,-2144373,17846988,-13971927 },
+ },
+},
+{
+ {
+ { -2244452,-754728,-4597030,-1066309,-6247172,1455299,-21647728,-9214789,-5222701,12650267 },
+ { -9906797,-16070310,21134160,12198166,-27064575,708126,387813,13770293,-19134326,10958663 },
+ { 22470984,12369526,23446014,-5441109,-21520802,-9698723,-11772496,-11574455,-25083830,4271862 },
+ },
+ {
+ { -25169565,-10053642,-19909332,15361595,-5984358,2159192,75375,-4278529,-32526221,8469673 },
+ { 15854970,4148314,-8893890,7259002,11666551,13824734,-30531198,2697372,24154791,-9460943 },
+ { 15446137,-15806644,29759747,14019369,30811221,-9610191,-31582008,12840104,24913809,9815020 },
+ },
+ {
+ { -4709286,-5614269,-31841498,-12288893,-14443537,10799414,-9103676,13438769,18735128,9466238 },
+ { 11933045,9281483,5081055,-5183824,-2628162,-4905629,-7727821,-10896103,-22728655,16199064 },
+ { 14576810,379472,-26786533,-8317236,-29426508,-10812974,-102766,1876699,30801119,2164795 },
+ },
+ {
+ { 15995086,3199873,13672555,13712240,-19378835,-4647646,-13081610,-15496269,-13492807,1268052 },
+ { -10290614,-3659039,-3286592,10948818,23037027,3794475,-3470338,-12600221,-17055369,3565904 },
+ { 29210088,-9419337,-5919792,-4952785,10834811,-13327726,-16512102,-10820713,-27162222,-14030531 },
+ },
+ {
+ { -13161890,15508588,16663704,-8156150,-28349942,9019123,-29183421,-3769423,2244111,-14001979 },
+ { -5152875,-3800936,-9306475,-6071583,16243069,14684434,-25673088,-16180800,13491506,4641841 },
+ { 10813417,643330,-19188515,-728916,30292062,-16600078,27548447,-7721242,14476989,-12767431 },
+ },
+ {
+ { 10292079,9984945,6481436,8279905,-7251514,7032743,27282937,-1644259,-27912810,12651324 },
+ { -31185513,-813383,22271204,11835308,10201545,15351028,17099662,3988035,21721536,-3148940 },
+ { 10202177,-6545839,-31373232,-9574638,-32150642,-8119683,-12906320,3852694,13216206,14842320 },
+ },
+ {
+ { -15815640,-10601066,-6538952,-7258995,-6984659,-6581778,-31500847,13765824,-27434397,9900184 },
+ { 14465505,-13833331,-32133984,-14738873,-27443187,12990492,33046193,15796406,-7051866,-8040114 },
+ { 30924417,-8279620,6359016,-12816335,16508377,9071735,-25488601,15413635,9524356,-7018878 },
+ },
+ {
+ { 12274201,-13175547,32627641,-1785326,6736625,13267305,5237659,-5109483,15663516,4035784 },
+ { -2951309,8903985,17349946,601635,-16432815,-4612556,-13732739,-15889334,-22258478,4659091 },
+ { -16916263,-4952973,-30393711,-15158821,20774812,15897498,5736189,15026997,-2178256,-13455585 },
+ },
+},
+{
+ {
+ { -8858980,-2219056,28571666,-10155518,-474467,-10105698,-3801496,278095,23440562,-290208 },
+ { 10226241,-5928702,15139956,120818,-14867693,5218603,32937275,11551483,-16571960,-7442864 },
+ { 17932739,-12437276,-24039557,10749060,11316803,7535897,22503767,5561594,-3646624,3898661 },
+ },
+ {
+ { 7749907,-969567,-16339731,-16464,-25018111,15122143,-1573531,7152530,21831162,1245233 },
+ { 26958459,-14658026,4314586,8346991,-5677764,11960072,-32589295,-620035,-30402091,-16716212 },
+ { -12165896,9166947,33491384,13673479,29787085,13096535,6280834,14587357,-22338025,13987525 },
+ },
+ {
+ { -24349909,7778775,21116000,15572597,-4833266,-5357778,-4300898,-5124639,-7469781,-2858068 },
+ { 9681908,-6737123,-31951644,13591838,-6883821,386950,31622781,6439245,-14581012,4091397 },
+ { -8426427,1470727,-28109679,-1596990,3978627,-5123623,-19622683,12092163,29077877,-14741988 },
+ },
+ {
+ { 5269168,-6859726,-13230211,-8020715,25932563,1763552,-5606110,-5505881,-20017847,2357889 },
+ { 32264008,-15407652,-5387735,-1160093,-2091322,-3946900,23104804,-12869908,5727338,189038 },
+ { 14609123,-8954470,-6000566,-16622781,-14577387,-7743898,-26745169,10942115,-25888931,-14884697 },
+ },
+ {
+ { 20513500,5557931,-15604613,7829531,26413943,-2019404,-21378968,7471781,13913677,-5137875 },
+ { -25574376,11967826,29233242,12948236,-6754465,4713227,-8940970,14059180,12878652,8511905 },
+ { -25656801,3393631,-2955415,-7075526,-2250709,9366908,-30223418,6812974,5568676,-3127656 },
+ },
+ {
+ { 11630004,12144454,2116339,13606037,27378885,15676917,-17408753,-13504373,-14395196,8070818 },
+ { 27117696,-10007378,-31282771,-5570088,1127282,12772488,-29845906,10483306,-11552749,-1028714 },
+ { 10637467,-5688064,5674781,1072708,-26343588,-6982302,-1683975,9177853,-27493162,15431203 },
+ },
+ {
+ { 20525145,10892566,-12742472,12779443,-29493034,16150075,-28240519,14943142,-15056790,-7935931 },
+ { -30024462,5626926,-551567,-9981087,753598,11981191,25244767,-3239766,-3356550,9594024 },
+ { -23752644,2636870,-5163910,-10103818,585134,7877383,11345683,-6492290,13352335,-10977084 },
+ },
+ {
+ { -1931799,-5407458,3304649,-12884869,17015806,-4877091,-29783850,-7752482,-13215537,-319204 },
+ { 20239939,6607058,6203985,3483793,-18386976,-779229,-20723742,15077870,-22750759,14523817 },
+ { 27406042,-6041657,27423596,-4497394,4996214,10002360,-28842031,-4545494,-30172742,-4805667 },
+ },
+},
+{
+ {
+ { 11374242,12660715,17861383,-12540833,10935568,1099227,-13886076,-9091740,-27727044,11358504 },
+ { -12730809,10311867,1510375,10778093,-2119455,-9145702,32676003,11149336,-26123651,4985768 },
+ { -19096303,341147,-6197485,-239033,15756973,-8796662,-983043,13794114,-19414307,-15621255 },
+ },
+ {
+ { 6490081,11940286,25495923,-7726360,8668373,-8751316,3367603,6970005,-1691065,-9004790 },
+ { 1656497,13457317,15370807,6364910,13605745,8362338,-19174622,-5475723,-16796596,-5031438 },
+ { -22273315,-13524424,-64685,-4334223,-18605636,-10921968,-20571065,-7007978,-99853,-10237333 },
+ },
+ {
+ { 17747465,10039260,19368299,-4050591,-20630635,-16041286,31992683,-15857976,-29260363,-5511971 },
+ { 31932027,-4986141,-19612382,16366580,22023614,88450,11371999,-3744247,4882242,-10626905 },
+ { 29796507,37186,19818052,10115756,-11829032,3352736,18551198,3272828,-5190932,-4162409 },
+ },
+ {
+ { 12501286,4044383,-8612957,-13392385,-32430052,5136599,-19230378,-3529697,330070,-3659409 },
+ { 6384877,2899513,17807477,7663917,-2358888,12363165,25366522,-8573892,-271295,12071499 },
+ { -8365515,-4042521,25133448,-4517355,-6211027,2265927,-32769618,1936675,-5159697,3829363 },
+ },
+ {
+ { 28425966,-5835433,-577090,-4697198,-14217555,6870930,7921550,-6567787,26333140,14267664 },
+ { -11067219,11871231,27385719,-10559544,-4585914,-11189312,10004786,-8709488,-21761224,8930324 },
+ { -21197785,-16396035,25654216,-1725397,12282012,11008919,1541940,4757911,-26491501,-16408940 },
+ },
+ {
+ { 13537262,-7759490,-20604840,10961927,-5922820,-13218065,-13156584,6217254,-15943699,13814990 },
+ { -17422573,15157790,18705543,29619,24409717,-260476,27361681,9257833,-1956526,-1776914 },
+ { -25045300,-10191966,15366585,15166509,-13105086,8423556,-29171540,12361135,-18685978,4578290 },
+ },
+ {
+ { 24579768,3711570,1342322,-11180126,-27005135,14124956,-22544529,14074919,21964432,8235257 },
+ { -6528613,-2411497,9442966,-5925588,12025640,-1487420,-2981514,-1669206,13006806,2355433 },
+ { -16304899,-13605259,-6632427,-5142349,16974359,-10911083,27202044,1719366,1141648,-12796236 },
+ },
+ {
+ { -12863944,-13219986,-8318266,-11018091,-6810145,-4843894,13475066,-3133972,32674895,13715045 },
+ { 11423335,-5468059,32344216,8962751,24989809,9241752,-13265253,16086212,-28740881,-15642093 },
+ { -1409668,12530728,-6368726,10847387,19531186,-14132160,-11709148,7791794,-27245943,4383347 },
+ },
+},
+{
+ {
+ { -28970898,5271447,-1266009,-9736989,-12455236,16732599,-4862407,-4906449,27193557,6245191 },
+ { -15193956,5362278,-1783893,2695834,4960227,12840725,23061898,3260492,22510453,8577507 },
+ { -12632451,11257346,-32692994,13548177,-721004,10879011,31168030,13952092,-29571492,-3635906 },
+ },
+ {
+ { 3877321,-9572739,32416692,5405324,-11004407,-13656635,3759769,11935320,5611860,8164018 },
+ { -16275802,14667797,15906460,12155291,-22111149,-9039718,32003002,-8832289,5773085,-8422109 },
+ { -23788118,-8254300,1950875,8937633,18686727,16459170,-905725,12376320,31632953,190926 },
+ },
+ {
+ { -24593607,-16138885,-8423991,13378746,14162407,6901328,-8288749,4508564,-25341555,-3627528 },
+ { 8884438,-5884009,6023974,10104341,-6881569,-4941533,18722941,-14786005,-1672488,827625 },
+ { -32720583,-16289296,-32503547,7101210,13354605,2659080,-1800575,-14108036,-24878478,1541286 },
+ },
+ {
+ { 2901347,-1117687,3880376,-10059388,-17620940,-3612781,-21802117,-3567481,20456845,-1885033 },
+ { 27019610,12299467,-13658288,-1603234,-12861660,-4861471,-19540150,-5016058,29439641,15138866 },
+ { 21536104,-6626420,-32447818,-10690208,-22408077,5175814,-5420040,-16361163,7779328,109896 },
+ },
+ {
+ { 30279744,14648750,-8044871,6425558,13639621,-743509,28698390,12180118,23177719,-554075 },
+ { 26572847,3405927,-31701700,12890905,-19265668,5335866,-6493768,2378492,4439158,-13279347 },
+ { -22716706,3489070,-9225266,-332753,18875722,-1140095,14819434,-12731527,-17717757,-5461437 },
+ },
+ {
+ { -5056483,16566551,15953661,3767752,-10436499,15627060,-820954,2177225,8550082,-15114165 },
+ { -18473302,16596775,-381660,15663611,22860960,15585581,-27844109,-3582739,-23260460,-8428588 },
+ { -32480551,15707275,-8205912,-5652081,29464558,2713815,-22725137,15860482,-21902570,1494193 },
+ },
+ {
+ { -19562091,-14087393,-25583872,-9299552,13127842,759709,21923482,16529112,8742704,12967017 },
+ { -28464899,1553205,32536856,-10473729,-24691605,-406174,-8914625,-2933896,-29903758,15553883 },
+ { 21877909,3230008,9881174,10539357,-4797115,2841332,11543572,14513274,19375923,-12647961 },
+ },
+ {
+ { 8832269,-14495485,13253511,5137575,5037871,4078777,24880818,-6222716,2862653,9455043 },
+ { 29306751,5123106,20245049,-14149889,9592566,8447059,-2077124,-2990080,15511449,4789663 },
+ { -20679756,7004547,8824831,-9434977,-4045704,-3750736,-5754762,108893,23513200,16652362 },
+ },
+},
+{
+ {
+ { -33256173,4144782,-4476029,-6579123,10770039,-7155542,-6650416,-12936300,-18319198,10212860 },
+ { 2756081,8598110,7383731,-6859892,22312759,-1105012,21179801,2600940,-9988298,-12506466 },
+ { -24645692,13317462,-30449259,-15653928,21365574,-10869657,11344424,864440,-2499677,-16710063 },
+ },
+ {
+ { -26432803,6148329,-17184412,-14474154,18782929,-275997,-22561534,211300,2719757,4940997 },
+ { -1323882,3911313,-6948744,14759765,-30027150,7851207,21690126,8518463,26699843,5276295 },
+ { -13149873,-6429067,9396249,365013,24703301,-10488939,1321586,149635,-15452774,7159369 },
+ },
+ {
+ { 9987780,-3404759,17507962,9505530,9731535,-2165514,22356009,8312176,22477218,-8403385 },
+ { 18155857,-16504990,19744716,9006923,15154154,-10538976,24256460,-4864995,-22548173,9334109 },
+ { 2986088,-4911893,10776628,-3473844,10620590,-7083203,-21413845,14253545,-22587149,536906 },
+ },
+ {
+ { 4377756,8115836,24567078,15495314,11625074,13064599,7390551,10589625,10838060,-15420424 },
+ { -19342404,867880,9277171,-3218459,-14431572,-1986443,19295826,-15796950,6378260,699185 },
+ { 7895026,4057113,-7081772,-13077756,-17886831,-323126,-716039,15693155,-5045064,-13373962 },
+ },
+ {
+ { -7737563,-5869402,-14566319,-7406919,11385654,13201616,31730678,-10962840,-3918636,-9669325 },
+ { 10188286,-15770834,-7336361,13427543,22223443,14896287,30743455,7116568,-21786507,5427593 },
+ { 696102,13206899,27047647,-10632082,15285305,-9853179,10798490,-4578720,19236243,12477404 },
+ },
+ {
+ { -11229439,11243796,-17054270,-8040865,-788228,-8167967,-3897669,11180504,-23169516,7733644 },
+ { 17800790,-14036179,-27000429,-11766671,23887827,3149671,23466177,-10538171,10322027,15313801 },
+ { 26246234,11968874,32263343,-5468728,6830755,-13323031,-15794704,-101982,-24449242,10890804 },
+ },
+ {
+ { -31365647,10271363,-12660625,-6267268,16690207,-13062544,-14982212,16484931,25180797,-5334884 },
+ { -586574,10376444,-32586414,-11286356,19801893,10997610,2276632,9482883,316878,13820577 },
+ { -9882808,-4510367,-2115506,16457136,-11100081,11674996,30756178,-7515054,30696930,-3712849 },
+ },
+ {
+ { 32988917,-9603412,12499366,7910787,-10617257,-11931514,-7342816,-9985397,-32349517,7392473 },
+ { -8855661,15927861,9866406,-3649411,-2396914,-16655781,-30409476,-9134995,25112947,-2926644 },
+ { -2504044,-436966,25621774,-5678772,15085042,-5479877,-24884878,-13526194,5537438,-13914319 },
+ },
+},
+{
+ {
+ { -11225584,2320285,-9584280,10149187,-33444663,5808648,-14876251,-1729667,31234590,6090599 },
+ { -9633316,116426,26083934,2897444,-6364437,-2688086,609721,15878753,-6970405,-9034768 },
+ { -27757857,247744,-15194774,-9002551,23288161,-10011936,-23869595,6503646,20650474,1804084 },
+ },
+ {
+ { -27589786,15456424,8972517,8469608,15640622,4439847,3121995,-10329713,27842616,-202328 },
+ { -15306973,2839644,22530074,10026331,4602058,5048462,28248656,5031932,-11375082,12714369 },
+ { 20807691,-7270825,29286141,11421711,-27876523,-13868230,-21227475,1035546,-19733229,12796920 },
+ },
+ {
+ { 12076899,-14301286,-8785001,-11848922,-25012791,16400684,-17591495,-12899438,3480665,-15182815 },
+ { -32361549,5457597,28548107,7833186,7303070,-11953545,-24363064,-15921875,-33374054,2771025 },
+ { -21389266,421932,26597266,6860826,22486084,-6737172,-17137485,-4210226,-24552282,15673397 },
+ },
+ {
+ { -20184622,2338216,19788685,-9620956,-4001265,-8740893,-20271184,4733254,3727144,-12934448 },
+ { 6120119,814863,-11794402,-622716,6812205,-15747771,2019594,7975683,31123697,-10958981 },
+ { 30069250,-11435332,30434654,2958439,18399564,-976289,12296869,9204260,-16432438,9648165 },
+ },
+ {
+ { 32705432,-1550977,30705658,7451065,-11805606,9631813,3305266,5248604,-26008332,-11377501 },
+ { 17219865,2375039,-31570947,-5575615,-19459679,9219903,294711,15298639,2662509,-16297073 },
+ { -1172927,-7558695,-4366770,-4287744,-21346413,-8434326,32087529,-1222777,32247248,-14389861 },
+ },
+ {
+ { 14312628,1221556,17395390,-8700143,-4945741,-8684635,-28197744,-9637817,-16027623,-13378845 },
+ { -1428825,-9678990,-9235681,6549687,-7383069,-468664,23046502,9803137,17597934,2346211 },
+ { 18510800,15337574,26171504,981392,-22241552,7827556,-23491134,-11323352,3059833,-11782870 },
+ },
+ {
+ { 10141598,6082907,17829293,-1947643,9830092,13613136,-25556636,-5544586,-33502212,3592096 },
+ { 33114168,-15889352,-26525686,-13343397,33076705,8716171,1151462,1521897,-982665,-6837803 },
+ { -32939165,-4255815,23947181,-324178,-33072974,-12305637,-16637686,3891704,26353178,693168 },
+ },
+ {
+ { 30374239,1595580,-16884039,13186931,4600344,406904,9585294,-400668,31375464,14369965 },
+ { -14370654,-7772529,1510301,6434173,-18784789,-6262728,32732230,-13108839,17901441,16011505 },
+ { 18171223,-11934626,-12500402,15197122,-11038147,-15230035,-19172240,-16046376,8764035,12309598 },
+ },
+},
+{
+ {
+ { 5975908,-5243188,-19459362,-9681747,-11541277,14015782,-23665757,1228319,17544096,-10593782 },
+ { 5811932,-1715293,3442887,-2269310,-18367348,-8359541,-18044043,-15410127,-5565381,12348900 },
+ { -31399660,11407555,25755363,6891399,-3256938,14872274,-24849353,8141295,-10632534,-585479 },
+ },
+ {
+ { -12675304,694026,-5076145,13300344,14015258,-14451394,-9698672,-11329050,30944593,1130208 },
+ { 8247766,-6710942,-26562381,-7709309,-14401939,-14648910,4652152,2488540,23550156,-271232 },
+ { 17294316,-3788438,7026748,15626851,22990044,113481,2267737,-5908146,-408818,-137719 },
+ },
+ {
+ { 16091085,-16253926,18599252,7340678,2137637,-1221657,-3364161,14550936,3260525,-7166271 },
+ { -4910104,-13332887,18550887,10864893,-16459325,-7291596,-23028869,-13204905,-12748722,2701326 },
+ { -8574695,16099415,4629974,-16340524,-20786213,-6005432,-10018363,9276971,11329923,1862132 },
+ },
+ {
+ { 14763076,-15903608,-30918270,3689867,3511892,10313526,-21951088,12219231,-9037963,-940300 },
+ { 8894987,-3446094,6150753,3013931,301220,15693451,-31981216,-2909717,-15438168,11595570 },
+ { 15214962,3537601,-26238722,-14058872,4418657,-15230761,13947276,10730794,-13489462,-4363670 },
+ },
+ {
+ { -2538306,7682793,32759013,263109,-29984731,-7955452,-22332124,-10188635,977108,699994 },
+ { -12466472,4195084,-9211532,550904,-15565337,12917920,19118110,-439841,-30534533,-14337913 },
+ { 31788461,-14507657,4799989,7372237,8808585,-14747943,9408237,-10051775,12493932,-5409317 },
+ },
+ {
+ { -25680606,5260744,-19235809,-6284470,-3695942,16566087,27218280,2607121,29375955,6024730 },
+ { 842132,-2794693,-4763381,-8722815,26332018,-12405641,11831880,6985184,-9940361,2854096 },
+ { -4847262,-7969331,2516242,-5847713,9695691,-7221186,16512645,960770,12121869,16648078 },
+ },
+ {
+ { -15218652,14667096,-13336229,2013717,30598287,-464137,-31504922,-7882064,20237806,2838411 },
+ { -19288047,4453152,15298546,-16178388,22115043,-15972604,12544294,-13470457,1068881,-12499905 },
+ { -9558883,-16518835,33238498,13506958,30505848,-1114596,-8486907,-2630053,12521378,4845654 },
+ },
+ {
+ { -28198521,10744108,-2958380,10199664,7759311,-13088600,3409348,-873400,-6482306,-12885870 },
+ { -23561822,6230156,-20382013,10655314,-24040585,-11621172,10477734,-1240216,-3113227,13974498 },
+ { 12966261,15550616,-32038948,-1615346,21025980,-629444,5642325,7188737,18895762,12629579 },
+ },
+},
+{
+ {
+ { 14741879,-14946887,22177208,-11721237,1279741,8058600,11758140,789443,32195181,3895677 },
+ { 10758205,15755439,-4509950,9243698,-4879422,6879879,-2204575,-3566119,-8982069,4429647 },
+ { -2453894,15725973,-20436342,-10410672,-5803908,-11040220,-7135870,-11642895,18047436,-15281743 },
+ },
+ {
+ { -25173001,-11307165,29759956,11776784,-22262383,-15820455,10993114,-12850837,-17620701,-9408468 },
+ { 21987233,700364,-24505048,14972008,-7774265,-5718395,32155026,2581431,-29958985,8773375 },
+ { -25568350,454463,-13211935,16126715,25240068,8594567,20656846,12017935,-7874389,-13920155 },
+ },
+ {
+ { 6028182,6263078,-31011806,-11301710,-818919,2461772,-31841174,-5468042,-1721788,-2776725 },
+ { -12278994,16624277,987579,-5922598,32908203,1248608,7719845,-4166698,28408820,6816612 },
+ { -10358094,-8237829,19549651,-12169222,22082623,16147817,20613181,13982702,-10339570,5067943 },
+ },
+ {
+ { -30505967,-3821767,12074681,13582412,-19877972,2443951,-19719286,12746132,5331210,-10105944 },
+ { 30528811,3601899,-1957090,4619785,-27361822,-15436388,24180793,-12570394,27679908,-1648928 },
+ { 9402404,-13957065,32834043,10838634,-26580150,-13237195,26653274,-8685565,22611444,-12715406 },
+ },
+ {
+ { 22190590,1118029,22736441,15130463,-30460692,-5991321,19189625,-4648942,4854859,6622139 },
+ { -8310738,-2953450,-8262579,-3388049,-10401731,-271929,13424426,-3567227,26404409,13001963 },
+ { -31241838,-15415700,-2994250,8939346,11562230,-12840670,-26064365,-11621720,-15405155,11020693 },
+ },
+ {
+ { 1866042,-7949489,-7898649,-10301010,12483315,13477547,3175636,-12424163,28761762,1406734 },
+ { -448555,-1777666,13018551,3194501,-9580420,-11161737,24760585,-4347088,25577411,-13378680 },
+ { -24290378,4759345,-690653,-1852816,2066747,10693769,-29595790,9884936,-9368926,4745410 },
+ },
+ {
+ { -9141284,6049714,-19531061,-4341411,-31260798,9944276,-15462008,-11311852,10931924,-11931931 },
+ { -16561513,14112680,-8012645,4817318,-8040464,-11414606,-22853429,10856641,-20470770,13434654 },
+ { 22759489,-10073434,-16766264,-1871422,13637442,-10168091,1765144,-12654326,28445307,-5364710 },
+ },
+ {
+ { 29875063,12493613,2795536,-3786330,1710620,15181182,-10195717,-8788675,9074234,1167180 },
+ { -26205683,11014233,-9842651,-2635485,-26908120,7532294,-18716888,-9535498,3843903,9367684 },
+ { -10969595,-6403711,9591134,9582310,11349256,108879,16235123,8601684,-139197,4242895 },
+ },
+},
+{
+ {
+ { 22092954,-13191123,-2042793,-11968512,32186753,-11517388,-6574341,2470660,-27417366,16625501 },
+ { -11057722,3042016,13770083,-9257922,584236,-544855,-7770857,2602725,-27351616,14247413 },
+ { 6314175,-10264892,-32772502,15957557,-10157730,168750,-8618807,14290061,27108877,-1180880 },
+ },
+ {
+ { -8586597,-7170966,13241782,10960156,-32991015,-13794596,33547976,-11058889,-27148451,981874 },
+ { 22833440,9293594,-32649448,-13618667,-9136966,14756819,-22928859,-13970780,-10479804,-16197962 },
+ { -7768587,3326786,-28111797,10783824,19178761,14905060,22680049,13906969,-15933690,3797899 },
+ },
+ {
+ { 21721356,-4212746,-12206123,9310182,-3882239,-13653110,23740224,-2709232,20491983,-8042152 },
+ { 9209270,-15135055,-13256557,-6167798,-731016,15289673,25947805,15286587,30997318,-6703063 },
+ { 7392032,16618386,23946583,-8039892,-13265164,-1533858,-14197445,-2321576,17649998,-250080 },
+ },
+ {
+ { -9301088,-14193827,30609526,-3049543,-25175069,-1283752,-15241566,-9525724,-2233253,7662146 },
+ { -17558673,1763594,-33114336,15908610,-30040870,-12174295,7335080,-8472199,-3174674,3440183 },
+ { -19889700,-5977008,-24111293,-9688870,10799743,-16571957,40450,-4431835,4862400,1133 },
+ },
+ {
+ { -32856209,-7873957,-5422389,14860950,-16319031,7956142,7258061,311861,-30594991,-7379421 },
+ { -3773428,-1565936,28985340,7499440,24445838,9325937,29727763,16527196,18278453,15405622 },
+ { -4381906,8508652,-19898366,-3674424,-5984453,15149970,-13313598,843523,-21875062,13626197 },
+ },
+ {
+ { 2281448,-13487055,-10915418,-2609910,1879358,16164207,-10783882,3953792,13340839,15928663 },
+ { 31727126,-7179855,-18437503,-8283652,2875793,-16390330,-25269894,-7014826,-23452306,5964753 },
+ { 4100420,-5959452,-17179337,6017714,-18705837,12227141,-26684835,11344144,2538215,-7570755 },
+ },
+ {
+ { -9433605,6123113,11159803,-2156608,30016280,14966241,-20474983,1485421,-629256,-15958862 },
+ { -26804558,4260919,11851389,9658551,-32017107,16367492,-20205425,-13191288,11659922,-11115118 },
+ { 26180396,10015009,-30844224,-8581293,5418197,9480663,2231568,-10170080,33100372,-1306171 },
+ },
+ {
+ { 15121113,-5201871,-10389905,15427821,-27509937,-15992507,21670947,4486675,-5931810,-14466380 },
+ { 16166486,-9483733,-11104130,6023908,-31926798,-1364923,2340060,-16254968,-10735770,-10039824 },
+ { 28042865,-3557089,-12126526,12259706,-3717498,-6945899,6766453,-8689599,18036436,5803270 },
+ },
+},
+{
+ {
+ { -817581,6763912,11803561,1585585,10958447,-2671165,23855391,4598332,-6159431,-14117438 },
+ { -31031306,-14256194,17332029,-2383520,31312682,-5967183,696309,50292,-20095739,11763584 },
+ { -594563,-2514283,-32234153,12643980,12650761,14811489,665117,-12613632,-19773211,-10713562 },
+ },
+ {
+ { 30464590,-11262872,-4127476,-12734478,19835327,-7105613,-24396175,2075773,-17020157,992471 },
+ { 18357185,-6994433,7766382,16342475,-29324918,411174,14578841,8080033,-11574335,-10601610 },
+ { 19598397,10334610,12555054,2555664,18821899,-10339780,21873263,16014234,26224780,16452269 },
+ },
+ {
+ { -30223925,5145196,5944548,16385966,3976735,2009897,-11377804,-7618186,-20533829,3698650 },
+ { 14187449,3448569,-10636236,-10810935,-22663880,-3433596,7268410,-10890444,27394301,12015369 },
+ { 19695761,16087646,28032085,12999827,6817792,11427614,20244189,-1312777,-13259127,-3402461 },
+ },
+ {
+ { 30860103,12735208,-1888245,-4699734,-16974906,2256940,-8166013,12298312,-8550524,-10393462 },
+ { -5719826,-11245325,-1910649,15569035,26642876,-7587760,-5789354,-15118654,-4976164,12651793 },
+ { -2848395,9953421,11531313,-5282879,26895123,-12697089,-13118820,-16517902,9768698,-2533218 },
+ },
+ {
+ { -24719459,1894651,-287698,-4704085,15348719,-8156530,32767513,12765450,4940095,10678226 },
+ { 18860224,15980149,-18987240,-1562570,-26233012,-11071856,-7843882,13944024,-24372348,16582019 },
+ { -15504260,4970268,-29893044,4175593,-20993212,-2199756,-11704054,15444560,-11003761,7989037 },
+ },
+ {
+ { 31490452,5568061,-2412803,2182383,-32336847,4531686,-32078269,6200206,-19686113,-14800171 },
+ { -17308668,-15879940,-31522777,-2831,-32887382,16375549,8680158,-16371713,28550068,-6857132 },
+ { -28126887,-5688091,16837845,-1820458,-6850681,12700016,-30039981,4364038,1155602,5988841 },
+ },
+ {
+ { 21890435,-13272907,-12624011,12154349,-7831873,15300496,23148983,-4470481,24618407,8283181 },
+ { -33136107,-10512751,9975416,6841041,-31559793,16356536,3070187,-7025928,1466169,10740210 },
+ { -1509399,-15488185,-13503385,-10655916,32799044,909394,-13938903,-5779719,-32164649,-15327040 },
+ },
+ {
+ { 3960823,-14267803,-28026090,-15918051,-19404858,13146868,15567327,951507,-3260321,-573935 },
+ { 24740841,5052253,-30094131,8961361,25877428,6165135,-24368180,14397372,-7380369,-6144105 },
+ { -28888365,3510803,-28103278,-1158478,-11238128,-10631454,-15441463,-14453128,-1625486,-6494814 },
+ },
+},
+{
+ {
+ { 793299,-9230478,8836302,-6235707,-27360908,-2369593,33152843,-4885251,-9906200,-621852 },
+ { 5666233,525582,20782575,-8038419,-24538499,14657740,16099374,1468826,-6171428,-15186581 },
+ { -4859255,-3779343,-2917758,-6748019,7778750,11688288,-30404353,-9871238,-1558923,-9863646 },
+ },
+ {
+ { 10896332,-7719704,824275,472601,-19460308,3009587,25248958,14783338,-30581476,-15757844 },
+ { 10566929,12612572,-31944212,11118703,-12633376,12362879,21752402,8822496,24003793,14264025 },
+ { 27713862,-7355973,-11008240,9227530,27050101,2504721,23886875,-13117525,13958495,-5732453 },
+ },
+ {
+ { -23481610,4867226,-27247128,3900521,29838369,-8212291,-31889399,-10041781,7340521,-15410068 },
+ { 4646514,-8011124,-22766023,-11532654,23184553,8566613,31366726,-1381061,-15066784,-10375192 },
+ { -17270517,12723032,-16993061,14878794,21619651,-6197576,27584817,3093888,-8843694,3849921 },
+ },
+ {
+ { -9064912,2103172,25561640,-15125738,-5239824,9582958,32477045,-9017955,5002294,-15550259 },
+ { -12057553,-11177906,21115585,-13365155,8808712,-12030708,16489530,13378448,-25845716,12741426 },
+ { -5946367,10645103,-30911586,15390284,-3286982,-7118677,24306472,15852464,28834118,-7646072 },
+ },
+ {
+ { -17335748,-9107057,-24531279,9434953,-8472084,-583362,-13090771,455841,20461858,5491305 },
+ { 13669248,-16095482,-12481974,-10203039,-14569770,-11893198,-24995986,11293807,-28588204,-9421832 },
+ { 28497928,6272777,-33022994,14470570,8906179,-1225630,18504674,-14165166,29867745,-8795943 },
+ },
+ {
+ { -16207023,13517196,-27799630,-13697798,24009064,-6373891,-6367600,-13175392,22853429,-4012011 },
+ { 24191378,16712145,-13931797,15217831,14542237,1646131,18603514,-11037887,12876623,-2112447 },
+ { 17902668,4518229,-411702,-2829247,26878217,5258055,-12860753,608397,16031844,3723494 },
+ },
+ {
+ { -28632773,12763728,-20446446,7577504,33001348,-13017745,17558842,-7872890,23896954,-4314245 },
+ { -20005381,-12011952,31520464,605201,2543521,5991821,-2945064,7229064,-9919646,-8826859 },
+ { 28816045,298879,-28165016,-15920938,19000928,-1665890,-12680833,-2949325,-18051778,-2082915 },
+ },
+ {
+ { 16000882,-344896,3493092,-11447198,-29504595,-13159789,12577740,16041268,-19715240,7847707 },
+ { 10151868,10572098,27312476,7922682,14825339,4723128,-32855931,-6519018,-10020567,3852848 },
+ { -11430470,15697596,-21121557,-4420647,5386314,15063598,16514493,-15932110,29330899,-15076224 },
+ },
+},
+{
+ {
+ { -25499735,-4378794,-15222908,-6901211,16615731,2051784,3303702,15490,-27548796,12314391 },
+ { 15683520,-6003043,18109120,-9980648,15337968,-5997823,-16717435,15921866,16103996,-3731215 },
+ { -23169824,-10781249,13588192,-1628807,-3798557,-1074929,-19273607,5402699,-29815713,-9841101 },
+ },
+ {
+ { 23190676,2384583,-32714340,3462154,-29903655,-1529132,-11266856,8911517,-25205859,2739713 },
+ { 21374101,-3554250,-33524649,9874411,15377179,11831242,-33529904,6134907,4931255,11987849 },
+ { -7732,-2978858,-16223486,7277597,105524,-322051,-31480539,13861388,-30076310,10117930 },
+ },
+ {
+ { -29501170,-10744872,-26163768,13051539,-25625564,5089643,-6325503,6704079,12890019,15728940 },
+ { -21972360,-11771379,-951059,-4418840,14704840,2695116,903376,-10428139,12885167,8311031 },
+ { -17516482,5352194,10384213,-13811658,7506451,13453191,26423267,4384730,1888765,-5435404 },
+ },
+ {
+ { -25817338,-3107312,-13494599,-3182506,30896459,-13921729,-32251644,-12707869,-19464434,-3340243 },
+ { -23607977,-2665774,-526091,4651136,5765089,4618330,6092245,14845197,17151279,-9854116 },
+ { -24830458,-12733720,-15165978,10367250,-29530908,-265356,22825805,-7087279,-16866484,16176525 },
+ },
+ {
+ { -23583256,6564961,20063689,3798228,-4740178,7359225,2006182,-10363426,-28746253,-10197509 },
+ { -10626600,-4486402,-13320562,-5125317,3432136,-6393229,23632037,-1940610,32808310,1099883 },
+ { 15030977,5768825,-27451236,-2887299,-6427378,-15361371,-15277896,-6809350,2051441,-15225865 },
+ },
+ {
+ { -3362323,-7239372,7517890,9824992,23555850,295369,5148398,-14154188,-22686354,16633660 },
+ { 4577086,-16752288,13249841,-15304328,19958763,-14537274,18559670,-10759549,8402478,-9864273 },
+ { -28406330,-1051581,-26790155,-907698,-17212414,-11030789,9453451,-14980072,17983010,9967138 },
+ },
+ {
+ { -25762494,6524722,26585488,9969270,24709298,1220360,-1677990,7806337,17507396,3651560 },
+ { -10420457,-4118111,14584639,15971087,-15768321,8861010,26556809,-5574557,-18553322,-11357135 },
+ { 2839101,14284142,4029895,3472686,14402957,12689363,-26642121,8459447,-5605463,-7621941 },
+ },
+ {
+ { -4839289,-3535444,9744961,2871048,25113978,3187018,-25110813,-849066,17258084,-7977739 },
+ { 18164541,-10595176,-17154882,-1542417,19237078,-9745295,23357533,-15217008,26908270,12150756 },
+ { -30264870,-7647865,5112249,-7036672,-1499807,-6974257,43168,-5537701,-32302074,16215819 },
+ },
+},
+{
+ {
+ { -6898905,9824394,-12304779,-4401089,-31397141,-6276835,32574489,12532905,-7503072,-8675347 },
+ { -27343522,-16515468,-27151524,-10722951,946346,16291093,254968,7168080,21676107,-1943028 },
+ { 21260961,-8424752,-16831886,-11920822,-23677961,3968121,-3651949,-6215466,-3556191,-7913075 },
+ },
+ {
+ { 16544754,13250366,-16804428,15546242,-4583003,12757258,-2462308,-8680336,-18907032,-9662799 },
+ { -2415239,-15577728,18312303,4964443,-15272530,-12653564,26820651,16690659,25459437,-4564609 },
+ { -25144690,11425020,28423002,-11020557,-6144921,-15826224,9142795,-2391602,-6432418,-1644817 },
+ },
+ {
+ { -23104652,6253476,16964147,-3768872,-25113972,-12296437,-27457225,-16344658,6335692,7249989 },
+ { -30333227,13979675,7503222,-12368314,-11956721,-4621693,-30272269,2682242,25993170,-12478523 },
+ { 4364628,5930691,32304656,-10044554,-8054781,15091131,22857016,-10598955,31820368,15075278 },
+ },
+ {
+ { 31879134,-8918693,17258761,90626,-8041836,-4917709,24162788,-9650886,-17970238,12833045 },
+ { 19073683,14851414,-24403169,-11860168,7625278,11091125,-19619190,2074449,-9413939,14905377 },
+ { 24483667,-11935567,-2518866,-11547418,-1553130,15355506,-25282080,9253129,27628530,-7555480 },
+ },
+ {
+ { 17597607,8340603,19355617,552187,26198470,-3176583,4593324,-9157582,-14110875,15297016 },
+ { 510886,14337390,-31785257,16638632,6328095,2713355,-20217417,-11864220,8683221,2921426 },
+ { 18606791,11874196,27155355,-5281482,-24031742,6265446,-25178240,-1278924,4674690,13890525 },
+ },
+ {
+ { 13609624,13069022,-27372361,-13055908,24360586,9592974,14977157,9835105,4389687,288396 },
+ { 9922506,-519394,13613107,5883594,-18758345,-434263,-12304062,8317628,23388070,16052080 },
+ { 12720016,11937594,-31970060,-5028689,26900120,8561328,-20155687,-11632979,-14754271,-10812892 },
+ },
+ {
+ { 15961858,14150409,26716931,-665832,-22794328,13603569,11829573,7467844,-28822128,929275 },
+ { 11038231,-11582396,-27310482,-7316562,-10498527,-16307831,-23479533,-9371869,-21393143,2465074 },
+ { 20017163,-4323226,27915242,1529148,12396362,15675764,13817261,-9658066,2463391,-4622140 },
+ },
+ {
+ { -16358878,-12663911,-12065183,4996454,-1256422,1073572,9583558,12851107,4003896,12673717 },
+ { -1731589,-15155870,-3262930,16143082,19294135,13385325,14741514,-9103726,7903886,2348101 },
+ { 24536016,-16515207,12715592,-3862155,1511293,10047386,-3842346,-7129159,-28377538,10048127 },
+ },
+},
+{
+ {
+ { -12622226,-6204820,30718825,2591312,-10617028,12192840,18873298,-7297090,-32297756,15221632 },
+ { -26478122,-11103864,11546244,-1852483,9180880,7656409,-21343950,2095755,29769758,6593415 },
+ { -31994208,-2907461,4176912,3264766,12538965,-868111,26312345,-6118678,30958054,8292160 },
+ },
+ {
+ { 31429822,-13959116,29173532,15632448,12174511,-2760094,32808831,3977186,26143136,-3148876 },
+ { 22648901,1402143,-22799984,13746059,7936347,365344,-8668633,-1674433,-3758243,-2304625 },
+ { -15491917,8012313,-2514730,-12702462,-23965846,-10254029,-1612713,-1535569,-16664475,8194478 },
+ },
+ {
+ { 27338066,-7507420,-7414224,10140405,-19026427,-6589889,27277191,8855376,28572286,3005164 },
+ { 26287124,4821776,25476601,-4145903,-3764513,-15788984,-18008582,1182479,-26094821,-13079595 },
+ { -7171154,3178080,23970071,6201893,-17195577,-4489192,-21876275,-13982627,32208683,-1198248 },
+ },
+ {
+ { -16657702,2817643,-10286362,14811298,6024667,13349505,-27315504,-10497842,-27672585,-11539858 },
+ { 15941029,-9405932,-21367050,8062055,31876073,-238629,-15278393,-1444429,15397331,-4130193 },
+ { 8934485,-13485467,-23286397,-13423241,-32446090,14047986,31170398,-1441021,-27505566,15087184 },
+ },
+ {
+ { -18357243,-2156491,24524913,-16677868,15520427,-6360776,-15502406,11461896,16788528,-5868942 },
+ { -1947386,16013773,21750665,3714552,-17401782,-16055433,-3770287,-10323320,31322514,-11615635 },
+ { 21426655,-5650218,-13648287,-5347537,-28812189,-4920970,-18275391,-14621414,13040862,-12112948 },
+ },
+ {
+ { 11293895,12478086,-27136401,15083750,-29307421,14748872,14555558,-13417103,1613711,4896935 },
+ { -25894883,15323294,-8489791,-8057900,25967126,-13425460,2825960,-4897045,-23971776,-11267415 },
+ { -15924766,-5229880,-17443532,6410664,3622847,10243618,20615400,12405433,-23753030,-8436416 },
+ },
+ {
+ { -7091295,12556208,-20191352,9025187,-17072479,4333801,4378436,2432030,23097949,-566018 },
+ { 4565804,-16025654,20084412,-7842817,1724999,189254,24767264,10103221,-18512313,2424778 },
+ { 366633,-11976806,8173090,-6890119,30788634,5745705,-7168678,1344109,-3642553,12412659 },
+ },
+ {
+ { -24001791,7690286,14929416,-168257,-32210835,-13412986,24162697,-15326504,-3141501,11179385 },
+ { 18289522,-14724954,8056945,16430056,-21729724,7842514,-6001441,-1486897,-18684645,-11443503 },
+ { 476239,6601091,-6152790,-9723375,17503545,-4863900,27672959,13403813,11052904,5219329 },
+ },
+},
+{
+ {
+ { 20678546,-8375738,-32671898,8849123,-5009758,14574752,31186971,-3973730,9014762,-8579056 },
+ { -13644050,-10350239,-15962508,5075808,-1514661,-11534600,-33102500,9160280,8473550,-3256838 },
+ { 24900749,14435722,17209120,-15292541,-22592275,9878983,-7689309,-16335821,-24568481,11788948 },
+ },
+ {
+ { -3118155,-11395194,-13802089,14797441,9652448,-6845904,-20037437,10410733,-24568470,-1458691 },
+ { -15659161,16736706,-22467150,10215878,-9097177,7563911,11871841,-12505194,-18513325,8464118 },
+ { -23400612,8348507,-14585951,-861714,-3950205,-6373419,14325289,8628612,33313881,-8370517 },
+ },
+ {
+ { -20186973,-4967935,22367356,5271547,-1097117,-4788838,-24805667,-10236854,-8940735,-5818269 },
+ { -6948785,-1795212,-32625683,-16021179,32635414,-7374245,15989197,-12838188,28358192,-4253904 },
+ { -23561781,-2799059,-32351682,-1661963,-9147719,10429267,-16637684,4072016,-5351664,5596589 },
+ },
+ {
+ { -28236598,-3390048,12312896,6213178,3117142,16078565,29266239,2557221,1768301,15373193 },
+ { -7243358,-3246960,-4593467,-7553353,-127927,-912245,-1090902,-4504991,-24660491,3442910 },
+ { -30210571,5124043,14181784,8197961,18964734,-11939093,22597931,7176455,-18585478,13365930 },
+ },
+ {
+ { -7877390,-1499958,8324673,4690079,6261860,890446,24538107,-8570186,-9689599,-3031667 },
+ { 25008904,-10771599,-4305031,-9638010,16265036,15721635,683793,-11823784,15723479,-15163481 },
+ { -9660625,12374379,-27006999,-7026148,-7724114,-12314514,11879682,5400171,519526,-1235876 },
+ },
+ {
+ { 22258397,-16332233,-7869817,14613016,-22520255,-2950923,-20353881,7315967,16648397,7605640 },
+ { -8081308,-8464597,-8223311,9719710,19259459,-15348212,23994942,-5281555,-9468848,4763278 },
+ { -21699244,9220969,-15730624,1084137,-25476107,-2852390,31088447,-7764523,-11356529,728112 },
+ },
+ {
+ { 26047220,-11751471,-6900323,-16521798,24092068,9158119,-4273545,-12555558,-29365436,-5498272 },
+ { 17510331,-322857,5854289,8403524,17133918,-3112612,-28111007,12327945,10750447,10014012 },
+ { -10312768,3936952,9156313,-8897683,16498692,-994647,-27481051,-666732,3424691,7540221 },
+ },
+ {
+ { 30322361,-6964110,11361005,-4143317,7433304,4989748,-7071422,-16317219,-9244265,15258046 },
+ { 13054562,-2779497,19155474,469045,-12482797,4566042,5631406,2711395,1062915,-5136345 },
+ { -19240248,-11254599,-29509029,-7499965,-5835763,13005411,-6066489,12194497,32960380,1459310 },
+ },
+},
+{
+ {
+ { 19852034,7027924,23669353,10020366,8586503,-6657907,394197,-6101885,18638003,-11174937 },
+ { 31395534,15098109,26581030,8030562,-16527914,-5007134,9012486,-7584354,-6643087,-5442636 },
+ { -9192165,-2347377,-1997099,4529534,25766844,607986,-13222,9677543,-32294889,-6456008 },
+ },
+ {
+ { -2444496,-149937,29348902,8186665,1873760,12489863,-30934579,-7839692,-7852844,-8138429 },
+ { -15236356,-15433509,7766470,746860,26346930,-10221762,-27333451,10754588,-9431476,5203576 },
+ { 31834314,14135496,-770007,5159118,20917671,-16768096,-7467973,-7337524,31809243,7347066 },
+ },
+ {
+ { -9606723,-11874240,20414459,13033986,13716524,-11691881,19797970,-12211255,15192876,-2087490 },
+ { -12663563,-2181719,1168162,-3804809,26747877,-14138091,10609330,12694420,33473243,-13382104 },
+ { 33184999,11180355,15832085,-11385430,-1633671,225884,15089336,-11023903,-6135662,14480053 },
+ },
+ {
+ { 31308717,-5619998,31030840,-1897099,15674547,-6582883,5496208,13685227,27595050,8737275 },
+ { -20318852,-15150239,10933843,-16178022,8335352,-7546022,-31008351,-12610604,26498114,66511 },
+ { 22644454,-8761729,-16671776,4884562,-3105614,-13559366,30540766,-4286747,-13327787,-7515095 },
+ },
+ {
+ { -28017847,9834845,18617207,-2681312,-3401956,-13307506,8205540,13585437,-17127465,15115439 },
+ { 23711543,-672915,31206561,-8362711,6164647,-9709987,-33535882,-1426096,8236921,16492939 },
+ { -23910559,-13515526,-26299483,-4503841,25005590,-7687270,19574902,10071562,6708380,-6222424 },
+ },
+ {
+ { 2101391,-4930054,19702731,2367575,-15427167,1047675,5301017,9328700,29955601,-11678310 },
+ { 3096359,9271816,-21620864,-15521844,-14847996,-7592937,-25892142,-12635595,-9917575,6216608 },
+ { -32615849,338663,-25195611,2510422,-29213566,-13820213,24822830,-6146567,-26767480,7525079 },
+ },
+ {
+ { -23066649,-13985623,16133487,-7896178,-3389565,778788,-910336,-2782495,-19386633,11994101 },
+ { 21691500,-13624626,-641331,-14367021,3285881,-3483596,-25064666,9718258,-7477437,13381418 },
+ { 18445390,-4202236,14979846,11622458,-1727110,-3582980,23111648,-6375247,28535282,15779576 },
+ },
+ {
+ { 30098053,3089662,-9234387,16662135,-21306940,11308411,-14068454,12021730,9955285,-16303356 },
+ { 9734894,-14576830,-7473633,-9138735,2060392,11313496,-18426029,9924399,20194861,13380996 },
+ { -26378102,-7965207,-22167821,15789297,-18055342,-6168792,-1984914,15707771,26342023,10146099 },
+ },
+},
+{
+ {
+ { -26016874,-219943,21339191,-41388,19745256,-2878700,-29637280,2227040,21612326,-545728 },
+ { -13077387,1184228,23562814,-5970442,-20351244,-6348714,25764461,12243797,-20856566,11649658 },
+ { -10031494,11262626,27384172,2271902,26947504,-15997771,39944,6114064,33514190,2333242 },
+ },
+ {
+ { -21433588,-12421821,8119782,7219913,-21830522,-9016134,-6679750,-12670638,24350578,-13450001 },
+ { -4116307,-11271533,-23886186,4843615,-30088339,690623,-31536088,-10406836,8317860,12352766 },
+ { 18200138,-14475911,-33087759,-2696619,-23702521,-9102511,-23552096,-2287550,20712163,6719373 },
+ },
+ {
+ { 26656208,6075253,-7858556,1886072,-28344043,4262326,11117530,-3763210,26224235,-3297458 },
+ { -17168938,-14854097,-3395676,-16369877,-19954045,14050420,21728352,9493610,18620611,-16428628 },
+ { -13323321,13325349,11432106,5964811,18609221,6062965,-5269471,-9725556,-30701573,-16479657 },
+ },
+ {
+ { -23860538,-11233159,26961357,1640861,-32413112,-16737940,12248509,-5240639,13735342,1934062 },
+ { 25089769,6742589,17081145,-13406266,21909293,-16067981,-15136294,-3765346,-21277997,5473616 },
+ { 31883677,-7961101,1083432,-11572403,22828471,13290673,-7125085,12469656,29111212,-5451014 },
+ },
+ {
+ { 24244947,-15050407,-26262976,2791540,-14997599,16666678,24367466,6388839,-10295587,452383 },
+ { -25640782,-3417841,5217916,16224624,19987036,-4082269,-24236251,-5915248,15766062,8407814 },
+ { -20406999,13990231,15495425,16395525,5377168,15166495,-8917023,-4388953,-8067909,2276718 },
+ },
+ {
+ { 30157918,12924066,-17712050,9245753,19895028,3368142,-23827587,5096219,22740376,-7303417 },
+ { 2041139,-14256350,7783687,13876377,-25946985,-13352459,24051124,13742383,-15637599,13295222 },
+ { 33338237,-8505733,12532113,7977527,9106186,-1715251,-17720195,-4612972,-4451357,-14669444 },
+ },
+ {
+ { -20045281,5454097,-14346548,6447146,28862071,1883651,-2469266,-4141880,7770569,9620597 },
+ { 23208068,7979712,33071466,8149229,1758231,-10834995,30945528,-1694323,-33502340,-14767970 },
+ { 1439958,-16270480,-1079989,-793782,4625402,10647766,-5043801,1220118,30494170,-11440799 },
+ },
+ {
+ { -5037580,-13028295,-2970559,-3061767,15640974,-6701666,-26739026,926050,-1684339,-13333647 },
+ { 13908495,-3549272,30919928,-6273825,-21521863,7989039,9021034,9078865,3353509,4033511 },
+ { -29663431,-15113610,32259991,-344482,24295849,-12912123,23161163,8839127,27485041,7356032 },
+ },
+},
+{
+ {
+ { 9661027,705443,11980065,-5370154,-1628543,14661173,-6346142,2625015,28431036,-16771834 },
+ { -23839233,-8311415,-25945511,7480958,-17681669,-8354183,-22545972,14150565,15970762,4099461 },
+ { 29262576,16756590,26350592,-8793563,8529671,-11208050,13617293,-9937143,11465739,8317062 },
+ },
+ {
+ { -25493081,-6962928,32500200,-9419051,-23038724,-2302222,14898637,3848455,20969334,-5157516 },
+ { -20384450,-14347713,-18336405,13884722,-33039454,2842114,-21610826,-3649888,11177095,14989547 },
+ { -24496721,-11716016,16959896,2278463,12066309,10137771,13515641,2581286,-28487508,9930240 },
+ },
+ {
+ { -17751622,-2097826,16544300,-13009300,-15914807,-14949081,18345767,-13403753,16291481,-5314038 },
+ { -33229194,2553288,32678213,9875984,8534129,6889387,-9676774,6957617,4368891,9788741 },
+ { 16660756,7281060,-10830758,12911820,20108584,-8101676,-21722536,-8613148,16250552,-11111103 },
+ },
+ {
+ { -19765507,2390526,-16551031,14161980,1905286,6414907,4689584,10604807,-30190403,4782747 },
+ { -1354539,14736941,-7367442,-13292886,7710542,-14155590,-9981571,4383045,22546403,437323 },
+ { 31665577,-12180464,-16186830,1491339,-18368625,3294682,27343084,2786261,-30633590,-14097016 },
+ },
+ {
+ { -14467279,-683715,-33374107,7448552,19294360,14334329,-19690631,2355319,-19284671,-6114373 },
+ { 15121312,-15796162,6377020,-6031361,-10798111,-12957845,18952177,15496498,-29380133,11754228 },
+ { -2637277,-13483075,8488727,-14303896,12728761,-1622493,7141596,11724556,22761615,-10134141 },
+ },
+ {
+ { 16918416,11729663,-18083579,3022987,-31015732,-13339659,-28741185,-12227393,32851222,11717399 },
+ { 11166634,7338049,-6722523,4531520,-29468672,-7302055,31474879,3483633,-1193175,-4030831 },
+ { -185635,9921305,31456609,-13536438,-12013818,13348923,33142652,6546660,-19985279,-3948376 },
+ },
+ {
+ { -32460596,11266712,-11197107,-7899103,31703694,3855903,-8537131,-12833048,-30772034,-15486313 },
+ { -18006477,12709068,3991746,-6479188,-21491523,-10550425,-31135347,-16049879,10928917,3011958 },
+ { -6957757,-15594337,31696059,334240,29576716,14796075,-30831056,-12805180,18008031,10258577 },
+ },
+ {
+ { -22448644,15655569,7018479,-4410003,-30314266,-1201591,-1853465,1367120,25127874,6671743 },
+ { 29701166,-14373934,-10878120,9279288,-17568,13127210,21382910,11042292,25838796,4642684 },
+ { -20430234,14955537,-24126347,8124619,-5369288,-5990470,30468147,-13900640,18423289,4177476 },
+ },
+},
diff --git a/src/ext/ed25519/ref10/base.py b/src/ext/ed25519/ref10/base.py
new file mode 100644
index 0000000000..84accc8580
--- /dev/null
+++ b/src/ext/ed25519/ref10/base.py
@@ -0,0 +1,65 @@
+b = 256
+q = 2**255 - 19
+l = 2**252 + 27742317777372353535851937790883648493
+
+def expmod(b,e,m):
+ if e == 0: return 1
+ t = expmod(b,e/2,m)**2 % m
+ if e & 1: t = (t*b) % m
+ return t
+
+def inv(x):
+ return expmod(x,q-2,q)
+
+d = -121665 * inv(121666)
+I = expmod(2,(q-1)/4,q)
+
+def xrecover(y):
+ xx = (y*y-1) * inv(d*y*y+1)
+ x = expmod(xx,(q+3)/8,q)
+ if (x*x - xx) % q != 0: x = (x*I) % q
+ if x % 2 != 0: x = q-x
+ return x
+
+By = 4 * inv(5)
+Bx = xrecover(By)
+B = [Bx % q,By % q]
+
+def edwards(P,Q):
+ x1 = P[0]
+ y1 = P[1]
+ x2 = Q[0]
+ y2 = Q[1]
+ x3 = (x1*y2+x2*y1) * inv(1+d*x1*x2*y1*y2)
+ y3 = (y1*y2+x1*x2) * inv(1-d*x1*x2*y1*y2)
+ return [x3 % q,y3 % q]
+
+def radix255(x):
+ x = x % q
+ if x + x > q: x -= q
+ x = [x,0,0,0,0,0,0,0,0,0]
+ bits = [26,25,26,25,26,25,26,25,26,25]
+ for i in range(9):
+ carry = (x[i] + 2**(bits[i]-1)) / 2**bits[i]
+ x[i] -= carry * 2**bits[i]
+ x[i + 1] += carry
+ result = ""
+ for i in range(9):
+ result = result+str(x[i])+","
+ result = result+str(x[9])
+ return result
+
+Bi = B
+for i in range(32):
+ print "{"
+ Bij = Bi
+ for j in range(8):
+ print " {"
+ print " {",radix255(Bij[1]+Bij[0]),"},"
+ print " {",radix255(Bij[1]-Bij[0]),"},"
+ print " {",radix255(2*d*Bij[0]*Bij[1]),"},"
+ Bij = edwards(Bij,Bi)
+ print " },"
+ print "},"
+ for k in range(8):
+ Bi = edwards(Bi,Bi)
diff --git a/src/ext/ed25519/ref10/base2.h b/src/ext/ed25519/ref10/base2.h
new file mode 100644
index 0000000000..8c538440ff
--- /dev/null
+++ b/src/ext/ed25519/ref10/base2.h
@@ -0,0 +1,40 @@
+ {
+ { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 },
+ { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 },
+ { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 },
+ },
+ {
+ { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 },
+ { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 },
+ { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 },
+ },
+ {
+ { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 },
+ { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 },
+ { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 },
+ },
+ {
+ { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 },
+ { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 },
+ { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 },
+ },
+ {
+ { -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 },
+ { -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 },
+ { 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 },
+ },
+ {
+ { -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 },
+ { 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 },
+ { 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 },
+ },
+ {
+ { -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 },
+ { -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 },
+ { -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 },
+ },
+ {
+ { -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 },
+ { -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 },
+ { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 },
+ },
diff --git a/src/ext/ed25519/ref10/base2.py b/src/ext/ed25519/ref10/base2.py
new file mode 100644
index 0000000000..5e4e8739d0
--- /dev/null
+++ b/src/ext/ed25519/ref10/base2.py
@@ -0,0 +1,60 @@
+b = 256
+q = 2**255 - 19
+l = 2**252 + 27742317777372353535851937790883648493
+
+def expmod(b,e,m):
+ if e == 0: return 1
+ t = expmod(b,e/2,m)**2 % m
+ if e & 1: t = (t*b) % m
+ return t
+
+def inv(x):
+ return expmod(x,q-2,q)
+
+d = -121665 * inv(121666)
+I = expmod(2,(q-1)/4,q)
+
+def xrecover(y):
+ xx = (y*y-1) * inv(d*y*y+1)
+ x = expmod(xx,(q+3)/8,q)
+ if (x*x - xx) % q != 0: x = (x*I) % q
+ if x % 2 != 0: x = q-x
+ return x
+
+By = 4 * inv(5)
+Bx = xrecover(By)
+B = [Bx % q,By % q]
+
+def edwards(P,Q):
+ x1 = P[0]
+ y1 = P[1]
+ x2 = Q[0]
+ y2 = Q[1]
+ x3 = (x1*y2+x2*y1) * inv(1+d*x1*x2*y1*y2)
+ y3 = (y1*y2+x1*x2) * inv(1-d*x1*x2*y1*y2)
+ return [x3 % q,y3 % q]
+
+def radix255(x):
+ x = x % q
+ if x + x > q: x -= q
+ x = [x,0,0,0,0,0,0,0,0,0]
+ bits = [26,25,26,25,26,25,26,25,26,25]
+ for i in range(9):
+ carry = (x[i] + 2**(bits[i]-1)) / 2**bits[i]
+ x[i] -= carry * 2**bits[i]
+ x[i + 1] += carry
+ result = ""
+ for i in range(9):
+ result = result+str(x[i])+","
+ result = result+str(x[9])
+ return result
+
+Bi = B
+
+for i in range(8):
+ print " {"
+ print " {",radix255(Bi[1]+Bi[0]),"},"
+ print " {",radix255(Bi[1]-Bi[0]),"},"
+ print " {",radix255(2*d*Bi[0]*Bi[1]),"},"
+ print " },"
+ Bi = edwards(B,edwards(B,Bi))
diff --git a/src/ext/ed25519/ref10/blinding.c b/src/ext/ed25519/ref10/blinding.c
new file mode 100644
index 0000000000..4d9a9cbbe7
--- /dev/null
+++ b/src/ext/ed25519/ref10/blinding.c
@@ -0,0 +1,76 @@
+/* Added to ref10 for Tor. We place this in the public domain. Alternatively,
+ * you may have it under the Creative Commons 0 "CC0" license. */
+//#include "fe.h"
+#include "ge.h"
+#include "sc.h"
+#include "crypto_hash_sha512.h"
+#include "ed25519_ref10.h"
+
+#include <string.h>
+#include "crypto.h"
+
+static void
+gettweak(unsigned char *out, const unsigned char *param)
+{
+ const char str[] = "Derive temporary signing key";
+ crypto_hash_sha512_2(out, (const unsigned char*)str, strlen(str), param, 32);
+ out[0] &= 248; /* Is this necessary necessary ? */
+ out[31] &= 63;
+ out[31] |= 64;
+}
+
+int ed25519_ref10_blind_secret_key(unsigned char *out,
+ const unsigned char *inp,
+ const unsigned char *param)
+{
+ const char str[] = "Derive temporary signing key hash input";
+ unsigned char tweak[64];
+ unsigned char zero[32];
+ gettweak(tweak, param);
+
+ memset(zero, 0, 32);
+ sc_muladd(out, inp, tweak, zero);
+
+ crypto_hash_sha512_2(tweak, (const unsigned char *)str, strlen(str),
+ inp+32, 32);
+ memcpy(out+32, tweak, 32);
+
+ memwipe(tweak, 0, sizeof(tweak));
+
+ return 0;
+}
+
+int ed25519_ref10_blind_public_key(unsigned char *out,
+ const unsigned char *inp,
+ const unsigned char *param)
+{
+ unsigned char tweak[64];
+ unsigned char zero[32];
+ unsigned char pkcopy[32];
+ ge_p3 A;
+ ge_p2 Aprime;
+
+ gettweak(tweak, param);
+
+ memset(zero, 0, sizeof(zero));
+ /* Not the greatest implementation of all of this. I wish I had
+ * better-suited primitives to work with here... (but I don't wish that so
+ * strongly that I'm about to code my own ge_scalarmult_vartime). */
+
+ /* We negate the public key first, so that we can pass it to
+ * frombytes_negate_vartime, which negates it again. If there were a
+ * "ge_frombytes", we'd use that, but there isn't. */
+ memcpy(pkcopy, inp, 32);
+ pkcopy[31] ^= (1<<7);
+ ge_frombytes_negate_vartime(&A, pkcopy);
+ /* There isn't a regular ge_scalarmult -- we have to do tweak*A + zero*B. */
+ ge_double_scalarmult_vartime(&Aprime, tweak, &A, zero);
+ ge_tobytes(out, &Aprime);
+
+ memwipe(tweak, 0, sizeof(tweak));
+ memwipe(&A, 0, sizeof(A));
+ memwipe(&Aprime, 0, sizeof(Aprime));
+ memwipe(pkcopy, 0, sizeof(pkcopy));
+
+ return 0;
+}
diff --git a/src/ext/ed25519/ref10/crypto_hash_sha512.h b/src/ext/ed25519/ref10/crypto_hash_sha512.h
new file mode 100644
index 0000000000..0278571522
--- /dev/null
+++ b/src/ext/ed25519/ref10/crypto_hash_sha512.h
@@ -0,0 +1,30 @@
+/* Added for Tor. */
+#include <openssl/sha.h>
+
+/* Set 'out' to the 512-bit SHA512 hash of the 'len'-byte string in 'inp' */
+#define crypto_hash_sha512(out, inp, len) \
+ SHA512((inp), (len), (out))
+
+/* Set 'out' to the 512-bit SHA512 hash of the 'len1'-byte string in 'inp1',
+ * concatenated with the 'len2'-byte string in 'inp2'. */
+#define crypto_hash_sha512_2(out, inp1, len1, inp2, len2) \
+ do { \
+ SHA512_CTX sha_ctx_; \
+ SHA512_Init(&sha_ctx_); \
+ SHA512_Update(&sha_ctx_, (inp1), (len1)); \
+ SHA512_Update(&sha_ctx_, (inp2), (len2)); \
+ SHA512_Final((out), &sha_ctx_); \
+ } while(0)
+
+/* Set 'out' to the 512-bit SHA512 hash of the 'len1'-byte string in 'inp1',
+ * concatenated with the 'len2'-byte string in 'inp2', concatenated with
+ * the 'len3'-byte string in 'len3'. */
+#define crypto_hash_sha512_3(out, inp1, len1, inp2, len2, inp3, len3) \
+ do { \
+ SHA512_CTX sha_ctx_; \
+ SHA512_Init(&sha_ctx_); \
+ SHA512_Update(&sha_ctx_, (inp1), (len1)); \
+ SHA512_Update(&sha_ctx_, (inp2), (len2)); \
+ SHA512_Update(&sha_ctx_, (inp3), (len3)); \
+ SHA512_Final((out), &sha_ctx_); \
+ } while(0)
diff --git a/src/ext/ed25519/ref10/crypto_int32.h b/src/ext/ed25519/ref10/crypto_int32.h
new file mode 100644
index 0000000000..dd13c91bd0
--- /dev/null
+++ b/src/ext/ed25519/ref10/crypto_int32.h
@@ -0,0 +1,25 @@
+/* Added for Tor. */
+
+#ifndef CRYPTO_INT32_H
+#define CRYPTO_INT32_H
+
+#include "torint.h"
+#define crypto_int32 int32_t
+#define crypto_uint32 uint32_t
+
+/*
+ Stop signed left shifts overflowing
+ by using unsigned types for bitwise operations
+ */
+
+#ifndef OVERFLOW_SAFE_SIGNED_LSHIFT
+#define OVERFLOW_SAFE_SIGNED_LSHIFT(s, lshift, utype, stype) \
+ ((stype)((utype)(s) << (utype)(lshift)))
+#endif
+
+#define SHL32(s, lshift) \
+ OVERFLOW_SAFE_SIGNED_LSHIFT(s, lshift, crypto_uint32, crypto_int32)
+#define SHL8(s, lshift) \
+ OVERFLOW_SAFE_SIGNED_LSHIFT(s, lshift, unsigned char, signed char)
+
+#endif /* CRYPTO_INT32_H */
diff --git a/src/ext/ed25519/ref10/crypto_int64.h b/src/ext/ed25519/ref10/crypto_int64.h
new file mode 100644
index 0000000000..46e8852ed0
--- /dev/null
+++ b/src/ext/ed25519/ref10/crypto_int64.h
@@ -0,0 +1,23 @@
+/* Added for Tor. */
+
+#ifndef CRYPTO_INT64_H
+#define CRYPTO_INT64_H
+
+#include "torint.h"
+#define crypto_int64 int64_t
+#define crypto_uint64 uint64_t
+
+/*
+ Stop signed left shifts overflowing
+ by using unsigned types for bitwise operations
+ */
+
+#ifndef OVERFLOW_SAFE_SIGNED_LSHIFT
+#define OVERFLOW_SAFE_SIGNED_LSHIFT(s, lshift, utype, stype) \
+ ((stype)((utype)(s) << (utype)(lshift)))
+#endif
+
+#define SHL64(s, lshift) \
+ OVERFLOW_SAFE_SIGNED_LSHIFT(s, lshift, crypto_uint64, crypto_int64)
+
+#endif /* CRYPTO_INT64_H */
diff --git a/src/ext/ed25519/ref10/crypto_sign.h b/src/ext/ed25519/ref10/crypto_sign.h
new file mode 100644
index 0000000000..549626793a
--- /dev/null
+++ b/src/ext/ed25519/ref10/crypto_sign.h
@@ -0,0 +1,9 @@
+/* Added for Tor */
+#define crypto_sign ed25519_ref10_sign
+#define crypto_sign_keypair ed25519_ref10_keygen
+#define crypto_sign_seckey ed25519_ref10_seckey
+#define crypto_sign_seckey_expand ed25519_ref10_seckey_expand
+#define crypto_sign_pubkey ed25519_ref10_pubkey
+#define crypto_sign_open ed25519_ref10_open
+
+#include "ed25519_ref10.h"
diff --git a/src/ext/ed25519/ref10/crypto_uint32.h b/src/ext/ed25519/ref10/crypto_uint32.h
new file mode 100644
index 0000000000..62655a5b66
--- /dev/null
+++ b/src/ext/ed25519/ref10/crypto_uint32.h
@@ -0,0 +1,3 @@
+/* Added for Tor. */
+#include "torint.h"
+#define crypto_uint32 uint32_t
diff --git a/src/ext/ed25519/ref10/crypto_uint64.h b/src/ext/ed25519/ref10/crypto_uint64.h
new file mode 100644
index 0000000000..cbda882a6a
--- /dev/null
+++ b/src/ext/ed25519/ref10/crypto_uint64.h
@@ -0,0 +1,3 @@
+/* Added for Tor. */
+#include "torint.h"
+#define crypto_uint64 uint64_t
diff --git a/src/ext/ed25519/ref10/crypto_verify_32.h b/src/ext/ed25519/ref10/crypto_verify_32.h
new file mode 100644
index 0000000000..0f63efc7a3
--- /dev/null
+++ b/src/ext/ed25519/ref10/crypto_verify_32.h
@@ -0,0 +1,5 @@
+/* Added for Tor. */
+#include "di_ops.h"
+#define crypto_verify_32(a,b) \
+ (! tor_memeq((a), (b), 32))
+
diff --git a/src/ext/ed25519/ref10/d.h b/src/ext/ed25519/ref10/d.h
new file mode 100644
index 0000000000..e25f578350
--- /dev/null
+++ b/src/ext/ed25519/ref10/d.h
@@ -0,0 +1 @@
+-10913610,13857413,-15372611,6949391,114729,-8787816,-6275908,-3247719,-18696448,-12055116
diff --git a/src/ext/ed25519/ref10/d.py b/src/ext/ed25519/ref10/d.py
new file mode 100644
index 0000000000..8995bb86a3
--- /dev/null
+++ b/src/ext/ed25519/ref10/d.py
@@ -0,0 +1,28 @@
+q = 2**255 - 19
+
+def expmod(b,e,m):
+ if e == 0: return 1
+ t = expmod(b,e/2,m)**2 % m
+ if e & 1: t = (t*b) % m
+ return t
+
+def inv(x):
+ return expmod(x,q-2,q)
+
+def radix255(x):
+ x = x % q
+ if x + x > q: x -= q
+ x = [x,0,0,0,0,0,0,0,0,0]
+ bits = [26,25,26,25,26,25,26,25,26,25]
+ for i in range(9):
+ carry = (x[i] + 2**(bits[i]-1)) / 2**bits[i]
+ x[i] -= carry * 2**bits[i]
+ x[i + 1] += carry
+ result = ""
+ for i in range(9):
+ result = result+str(x[i])+","
+ result = result+str(x[9])
+ return result
+
+d = -121665 * inv(121666)
+print radix255(d)
diff --git a/src/ext/ed25519/ref10/d2.h b/src/ext/ed25519/ref10/d2.h
new file mode 100644
index 0000000000..01aaec7512
--- /dev/null
+++ b/src/ext/ed25519/ref10/d2.h
@@ -0,0 +1 @@
+-21827239,-5839606,-30745221,13898782,229458,15978800,-12551817,-6495438,29715968,9444199
diff --git a/src/ext/ed25519/ref10/d2.py b/src/ext/ed25519/ref10/d2.py
new file mode 100644
index 0000000000..79841758be
--- /dev/null
+++ b/src/ext/ed25519/ref10/d2.py
@@ -0,0 +1,28 @@
+q = 2**255 - 19
+
+def expmod(b,e,m):
+ if e == 0: return 1
+ t = expmod(b,e/2,m)**2 % m
+ if e & 1: t = (t*b) % m
+ return t
+
+def inv(x):
+ return expmod(x,q-2,q)
+
+def radix255(x):
+ x = x % q
+ if x + x > q: x -= q
+ x = [x,0,0,0,0,0,0,0,0,0]
+ bits = [26,25,26,25,26,25,26,25,26,25]
+ for i in range(9):
+ carry = (x[i] + 2**(bits[i]-1)) / 2**bits[i]
+ x[i] -= carry * 2**bits[i]
+ x[i + 1] += carry
+ result = ""
+ for i in range(9):
+ result = result+str(x[i])+","
+ result = result+str(x[9])
+ return result
+
+d = -121665 * inv(121666)
+print radix255(d*2)
diff --git a/src/ext/ed25519/ref10/ed25519_ref10.h b/src/ext/ed25519/ref10/ed25519_ref10.h
new file mode 100644
index 0000000000..af7e21a2ad
--- /dev/null
+++ b/src/ext/ed25519/ref10/ed25519_ref10.h
@@ -0,0 +1,30 @@
+/* Added for Tor */
+#ifndef SRC_EXT_ED25519_REF10_H_INCLUDED_
+#define SRC_EXT_ED25519_REF10_H_INCLUDED_
+#include <torint.h>
+
+int ed25519_ref10_seckey(unsigned char *sk);
+int ed25519_ref10_seckey_expand(unsigned char *sk, const unsigned char *sk_seed);
+int ed25519_ref10_pubkey(unsigned char *pk,const unsigned char *sk);
+int ed25519_ref10_keygen(unsigned char *pk,unsigned char *sk);
+int ed25519_ref10_open(
+ const unsigned char *signature,
+ const unsigned char *m, size_t mlen,
+ const unsigned char *pk);
+int ed25519_ref10_sign(
+ unsigned char *sig,
+ const unsigned char *m, size_t mlen,
+ const unsigned char *sk, const unsigned char *pk);
+
+/* Added in Tor */
+int ed25519_ref10_pubkey_from_curve25519_pubkey(unsigned char *out,
+ const unsigned char *inp,
+ int signbit);
+int ed25519_ref10_blind_secret_key(unsigned char *out,
+ const unsigned char *inp,
+ const unsigned char *param);
+int ed25519_ref10_blind_public_key(unsigned char *out,
+ const unsigned char *inp,
+ const unsigned char *param);
+
+#endif
diff --git a/src/ext/ed25519/ref10/fe.h b/src/ext/ed25519/ref10/fe.h
new file mode 100644
index 0000000000..60c308ba46
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe.h
@@ -0,0 +1,56 @@
+#ifndef FE_H
+#define FE_H
+
+#include "crypto_int32.h"
+
+typedef crypto_int32 fe[10];
+
+/*
+fe means field element.
+Here the field is \Z/(2^255-19).
+An element t, entries t[0]...t[9], represents the integer
+t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
+Bounds on each t[i] vary depending on context.
+*/
+
+#define fe_frombytes crypto_sign_ed25519_ref10_fe_frombytes
+#define fe_tobytes crypto_sign_ed25519_ref10_fe_tobytes
+#define fe_copy crypto_sign_ed25519_ref10_fe_copy
+#define fe_isnonzero crypto_sign_ed25519_ref10_fe_isnonzero
+#define fe_isnegative crypto_sign_ed25519_ref10_fe_isnegative
+#define fe_0 crypto_sign_ed25519_ref10_fe_0
+#define fe_1 crypto_sign_ed25519_ref10_fe_1
+#define fe_cswap crypto_sign_ed25519_ref10_fe_cswap
+#define fe_cmov crypto_sign_ed25519_ref10_fe_cmov
+#define fe_add crypto_sign_ed25519_ref10_fe_add
+#define fe_sub crypto_sign_ed25519_ref10_fe_sub
+#define fe_neg crypto_sign_ed25519_ref10_fe_neg
+#define fe_mul crypto_sign_ed25519_ref10_fe_mul
+#define fe_sq crypto_sign_ed25519_ref10_fe_sq
+#define fe_sq2 crypto_sign_ed25519_ref10_fe_sq2
+#define fe_mul121666 crypto_sign_ed25519_ref10_fe_mul121666
+#define fe_invert crypto_sign_ed25519_ref10_fe_invert
+#define fe_pow22523 crypto_sign_ed25519_ref10_fe_pow22523
+
+extern void fe_frombytes(fe,const unsigned char *);
+extern void fe_tobytes(unsigned char *,const fe);
+
+extern void fe_copy(fe,const fe);
+extern int fe_isnonzero(const fe);
+extern int fe_isnegative(const fe);
+extern void fe_0(fe);
+extern void fe_1(fe);
+extern void fe_cswap(fe,fe,unsigned int);
+extern void fe_cmov(fe,const fe,unsigned int);
+
+extern void fe_add(fe,const fe,const fe);
+extern void fe_sub(fe,const fe,const fe);
+extern void fe_neg(fe,const fe);
+extern void fe_mul(fe,const fe,const fe);
+extern void fe_sq(fe,const fe);
+extern void fe_sq2(fe,const fe);
+extern void fe_mul121666(fe,const fe);
+extern void fe_invert(fe,const fe);
+extern void fe_pow22523(fe,const fe);
+
+#endif
diff --git a/src/ext/ed25519/ref10/fe_0.c b/src/ext/ed25519/ref10/fe_0.c
new file mode 100644
index 0000000000..ec879d7337
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_0.c
@@ -0,0 +1,19 @@
+#include "fe.h"
+
+/*
+h = 0
+*/
+
+void fe_0(fe h)
+{
+ h[0] = 0;
+ h[1] = 0;
+ h[2] = 0;
+ h[3] = 0;
+ h[4] = 0;
+ h[5] = 0;
+ h[6] = 0;
+ h[7] = 0;
+ h[8] = 0;
+ h[9] = 0;
+}
diff --git a/src/ext/ed25519/ref10/fe_1.c b/src/ext/ed25519/ref10/fe_1.c
new file mode 100644
index 0000000000..8cf7784844
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_1.c
@@ -0,0 +1,19 @@
+#include "fe.h"
+
+/*
+h = 1
+*/
+
+void fe_1(fe h)
+{
+ h[0] = 1;
+ h[1] = 0;
+ h[2] = 0;
+ h[3] = 0;
+ h[4] = 0;
+ h[5] = 0;
+ h[6] = 0;
+ h[7] = 0;
+ h[8] = 0;
+ h[9] = 0;
+}
diff --git a/src/ext/ed25519/ref10/fe_add.c b/src/ext/ed25519/ref10/fe_add.c
new file mode 100644
index 0000000000..e6a81da202
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_add.c
@@ -0,0 +1,57 @@
+#include "fe.h"
+
+/*
+h = f + g
+Can overlap h with f or g.
+
+Preconditions:
+ |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+
+Postconditions:
+ |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+*/
+
+void fe_add(fe h,const fe f,const fe g)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 g0 = g[0];
+ crypto_int32 g1 = g[1];
+ crypto_int32 g2 = g[2];
+ crypto_int32 g3 = g[3];
+ crypto_int32 g4 = g[4];
+ crypto_int32 g5 = g[5];
+ crypto_int32 g6 = g[6];
+ crypto_int32 g7 = g[7];
+ crypto_int32 g8 = g[8];
+ crypto_int32 g9 = g[9];
+ crypto_int32 h0 = f0 + g0;
+ crypto_int32 h1 = f1 + g1;
+ crypto_int32 h2 = f2 + g2;
+ crypto_int32 h3 = f3 + g3;
+ crypto_int32 h4 = f4 + g4;
+ crypto_int32 h5 = f5 + g5;
+ crypto_int32 h6 = f6 + g6;
+ crypto_int32 h7 = f7 + g7;
+ crypto_int32 h8 = f8 + g8;
+ crypto_int32 h9 = f9 + g9;
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
diff --git a/src/ext/ed25519/ref10/fe_cmov.c b/src/ext/ed25519/ref10/fe_cmov.c
new file mode 100644
index 0000000000..8ca584fb19
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_cmov.c
@@ -0,0 +1,63 @@
+#include "fe.h"
+
+/*
+Replace (f,g) with (g,g) if b == 1;
+replace (f,g) with (f,g) if b == 0.
+
+Preconditions: b in {0,1}.
+*/
+
+void fe_cmov(fe f,const fe g,unsigned int b)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 g0 = g[0];
+ crypto_int32 g1 = g[1];
+ crypto_int32 g2 = g[2];
+ crypto_int32 g3 = g[3];
+ crypto_int32 g4 = g[4];
+ crypto_int32 g5 = g[5];
+ crypto_int32 g6 = g[6];
+ crypto_int32 g7 = g[7];
+ crypto_int32 g8 = g[8];
+ crypto_int32 g9 = g[9];
+ crypto_int32 x0 = f0 ^ g0;
+ crypto_int32 x1 = f1 ^ g1;
+ crypto_int32 x2 = f2 ^ g2;
+ crypto_int32 x3 = f3 ^ g3;
+ crypto_int32 x4 = f4 ^ g4;
+ crypto_int32 x5 = f5 ^ g5;
+ crypto_int32 x6 = f6 ^ g6;
+ crypto_int32 x7 = f7 ^ g7;
+ crypto_int32 x8 = f8 ^ g8;
+ crypto_int32 x9 = f9 ^ g9;
+ b = -b;
+ x0 &= b;
+ x1 &= b;
+ x2 &= b;
+ x3 &= b;
+ x4 &= b;
+ x5 &= b;
+ x6 &= b;
+ x7 &= b;
+ x8 &= b;
+ x9 &= b;
+ f[0] = f0 ^ x0;
+ f[1] = f1 ^ x1;
+ f[2] = f2 ^ x2;
+ f[3] = f3 ^ x3;
+ f[4] = f4 ^ x4;
+ f[5] = f5 ^ x5;
+ f[6] = f6 ^ x6;
+ f[7] = f7 ^ x7;
+ f[8] = f8 ^ x8;
+ f[9] = f9 ^ x9;
+}
diff --git a/src/ext/ed25519/ref10/fe_copy.c b/src/ext/ed25519/ref10/fe_copy.c
new file mode 100644
index 0000000000..9c5bf865a2
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_copy.c
@@ -0,0 +1,29 @@
+#include "fe.h"
+
+/*
+h = f
+*/
+
+void fe_copy(fe h,const fe f)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ h[0] = f0;
+ h[1] = f1;
+ h[2] = f2;
+ h[3] = f3;
+ h[4] = f4;
+ h[5] = f5;
+ h[6] = f6;
+ h[7] = f7;
+ h[8] = f8;
+ h[9] = f9;
+}
diff --git a/src/ext/ed25519/ref10/fe_frombytes.c b/src/ext/ed25519/ref10/fe_frombytes.c
new file mode 100644
index 0000000000..98b8e5f7c1
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_frombytes.c
@@ -0,0 +1,73 @@
+#include "fe.h"
+#include "crypto_int64.h"
+#include "crypto_uint64.h"
+
+static crypto_uint64 load_3(const unsigned char *in)
+{
+ crypto_uint64 result;
+ result = (crypto_uint64) in[0];
+ result |= ((crypto_uint64) in[1]) << 8;
+ result |= ((crypto_uint64) in[2]) << 16;
+ return result;
+}
+
+static crypto_uint64 load_4(const unsigned char *in)
+{
+ crypto_uint64 result;
+ result = (crypto_uint64) in[0];
+ result |= ((crypto_uint64) in[1]) << 8;
+ result |= ((crypto_uint64) in[2]) << 16;
+ result |= ((crypto_uint64) in[3]) << 24;
+ return result;
+}
+
+/*
+Ignores top bit of h.
+*/
+
+void fe_frombytes(fe h,const unsigned char *s)
+{
+ crypto_int64 h0 = load_4(s);
+ crypto_int64 h1 = load_3(s + 4) << 6;
+ crypto_int64 h2 = load_3(s + 7) << 5;
+ crypto_int64 h3 = load_3(s + 10) << 3;
+ crypto_int64 h4 = load_3(s + 13) << 2;
+ crypto_int64 h5 = load_4(s + 16);
+ crypto_int64 h6 = load_3(s + 20) << 7;
+ crypto_int64 h7 = load_3(s + 23) << 5;
+ crypto_int64 h8 = load_3(s + 26) << 4;
+ crypto_int64 h9 = (load_3(s + 29) & 8388607) << 2;
+ crypto_int64 carry0;
+ crypto_int64 carry1;
+ crypto_int64 carry2;
+ crypto_int64 carry3;
+ crypto_int64 carry4;
+ crypto_int64 carry5;
+ crypto_int64 carry6;
+ crypto_int64 carry7;
+ crypto_int64 carry8;
+ crypto_int64 carry9;
+
+ carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= SHL64(carry9,25);
+ carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= SHL64(carry1,25);
+ carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= SHL64(carry3,25);
+ carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= SHL64(carry5,25);
+ carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= SHL64(carry7,25);
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26);
+ carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= SHL64(carry2,26);
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26);
+ carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= SHL64(carry6,26);
+ carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= SHL64(carry8,26);
+
+ h[0] = (crypto_int32) h0;
+ h[1] = (crypto_int32) h1;
+ h[2] = (crypto_int32) h2;
+ h[3] = (crypto_int32) h3;
+ h[4] = (crypto_int32) h4;
+ h[5] = (crypto_int32) h5;
+ h[6] = (crypto_int32) h6;
+ h[7] = (crypto_int32) h7;
+ h[8] = (crypto_int32) h8;
+ h[9] = (crypto_int32) h9;
+}
diff --git a/src/ext/ed25519/ref10/fe_invert.c b/src/ext/ed25519/ref10/fe_invert.c
new file mode 100644
index 0000000000..bcfdb8ff87
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_invert.c
@@ -0,0 +1,14 @@
+#include "fe.h"
+
+void fe_invert(fe out,const fe z)
+{
+ fe t0;
+ fe t1;
+ fe t2;
+ fe t3;
+ int i;
+
+#include "pow225521.h"
+
+ return;
+}
diff --git a/src/ext/ed25519/ref10/fe_isnegative.c b/src/ext/ed25519/ref10/fe_isnegative.c
new file mode 100644
index 0000000000..3b2c8b8d52
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_isnegative.c
@@ -0,0 +1,16 @@
+#include "fe.h"
+
+/*
+return 1 if f is in {1,3,5,...,q-2}
+return 0 if f is in {0,2,4,...,q-1}
+
+Preconditions:
+ |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+*/
+
+int fe_isnegative(const fe f)
+{
+ unsigned char s[32];
+ fe_tobytes(s,f);
+ return s[0] & 1;
+}
diff --git a/src/ext/ed25519/ref10/fe_isnonzero.c b/src/ext/ed25519/ref10/fe_isnonzero.c
new file mode 100644
index 0000000000..47568001ce
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_isnonzero.c
@@ -0,0 +1,19 @@
+#include "fe.h"
+#include "crypto_verify_32.h"
+
+/*
+return 1 if f == 0
+return 0 if f != 0
+
+Preconditions:
+ |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+*/
+
+static const unsigned char zero[32];
+
+int fe_isnonzero(const fe f)
+{
+ unsigned char s[32];
+ fe_tobytes(s,f);
+ return crypto_verify_32(s,zero);
+}
diff --git a/src/ext/ed25519/ref10/fe_mul.c b/src/ext/ed25519/ref10/fe_mul.c
new file mode 100644
index 0000000000..ace63e64c1
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_mul.c
@@ -0,0 +1,253 @@
+#include "fe.h"
+#include "crypto_int64.h"
+
+/*
+h = f * g
+Can overlap h with f or g.
+
+Preconditions:
+ |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+ |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+
+Postconditions:
+ |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+*/
+
+/*
+Notes on implementation strategy:
+
+Using schoolbook multiplication.
+Karatsuba would save a little in some cost models.
+
+Most multiplications by 2 and 19 are 32-bit precomputations;
+cheaper than 64-bit postcomputations.
+
+There is one remaining multiplication by 19 in the carry chain;
+one *19 precomputation can be merged into this,
+but the resulting data flow is considerably less clean.
+
+There are 12 carries below.
+10 of them are 2-way parallelizable and vectorizable.
+Can get away with 11 carries, but then data flow is much deeper.
+
+With tighter constraints on inputs can squeeze carries into int32.
+*/
+
+void fe_mul(fe h,const fe f,const fe g)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 g0 = g[0];
+ crypto_int32 g1 = g[1];
+ crypto_int32 g2 = g[2];
+ crypto_int32 g3 = g[3];
+ crypto_int32 g4 = g[4];
+ crypto_int32 g5 = g[5];
+ crypto_int32 g6 = g[6];
+ crypto_int32 g7 = g[7];
+ crypto_int32 g8 = g[8];
+ crypto_int32 g9 = g[9];
+ crypto_int32 g1_19 = 19 * g1; /* 1.959375*2^29 */
+ crypto_int32 g2_19 = 19 * g2; /* 1.959375*2^30; still ok */
+ crypto_int32 g3_19 = 19 * g3;
+ crypto_int32 g4_19 = 19 * g4;
+ crypto_int32 g5_19 = 19 * g5;
+ crypto_int32 g6_19 = 19 * g6;
+ crypto_int32 g7_19 = 19 * g7;
+ crypto_int32 g8_19 = 19 * g8;
+ crypto_int32 g9_19 = 19 * g9;
+ crypto_int32 f1_2 = 2 * f1;
+ crypto_int32 f3_2 = 2 * f3;
+ crypto_int32 f5_2 = 2 * f5;
+ crypto_int32 f7_2 = 2 * f7;
+ crypto_int32 f9_2 = 2 * f9;
+ crypto_int64 f0g0 = f0 * (crypto_int64) g0;
+ crypto_int64 f0g1 = f0 * (crypto_int64) g1;
+ crypto_int64 f0g2 = f0 * (crypto_int64) g2;
+ crypto_int64 f0g3 = f0 * (crypto_int64) g3;
+ crypto_int64 f0g4 = f0 * (crypto_int64) g4;
+ crypto_int64 f0g5 = f0 * (crypto_int64) g5;
+ crypto_int64 f0g6 = f0 * (crypto_int64) g6;
+ crypto_int64 f0g7 = f0 * (crypto_int64) g7;
+ crypto_int64 f0g8 = f0 * (crypto_int64) g8;
+ crypto_int64 f0g9 = f0 * (crypto_int64) g9;
+ crypto_int64 f1g0 = f1 * (crypto_int64) g0;
+ crypto_int64 f1g1_2 = f1_2 * (crypto_int64) g1;
+ crypto_int64 f1g2 = f1 * (crypto_int64) g2;
+ crypto_int64 f1g3_2 = f1_2 * (crypto_int64) g3;
+ crypto_int64 f1g4 = f1 * (crypto_int64) g4;
+ crypto_int64 f1g5_2 = f1_2 * (crypto_int64) g5;
+ crypto_int64 f1g6 = f1 * (crypto_int64) g6;
+ crypto_int64 f1g7_2 = f1_2 * (crypto_int64) g7;
+ crypto_int64 f1g8 = f1 * (crypto_int64) g8;
+ crypto_int64 f1g9_38 = f1_2 * (crypto_int64) g9_19;
+ crypto_int64 f2g0 = f2 * (crypto_int64) g0;
+ crypto_int64 f2g1 = f2 * (crypto_int64) g1;
+ crypto_int64 f2g2 = f2 * (crypto_int64) g2;
+ crypto_int64 f2g3 = f2 * (crypto_int64) g3;
+ crypto_int64 f2g4 = f2 * (crypto_int64) g4;
+ crypto_int64 f2g5 = f2 * (crypto_int64) g5;
+ crypto_int64 f2g6 = f2 * (crypto_int64) g6;
+ crypto_int64 f2g7 = f2 * (crypto_int64) g7;
+ crypto_int64 f2g8_19 = f2 * (crypto_int64) g8_19;
+ crypto_int64 f2g9_19 = f2 * (crypto_int64) g9_19;
+ crypto_int64 f3g0 = f3 * (crypto_int64) g0;
+ crypto_int64 f3g1_2 = f3_2 * (crypto_int64) g1;
+ crypto_int64 f3g2 = f3 * (crypto_int64) g2;
+ crypto_int64 f3g3_2 = f3_2 * (crypto_int64) g3;
+ crypto_int64 f3g4 = f3 * (crypto_int64) g4;
+ crypto_int64 f3g5_2 = f3_2 * (crypto_int64) g5;
+ crypto_int64 f3g6 = f3 * (crypto_int64) g6;
+ crypto_int64 f3g7_38 = f3_2 * (crypto_int64) g7_19;
+ crypto_int64 f3g8_19 = f3 * (crypto_int64) g8_19;
+ crypto_int64 f3g9_38 = f3_2 * (crypto_int64) g9_19;
+ crypto_int64 f4g0 = f4 * (crypto_int64) g0;
+ crypto_int64 f4g1 = f4 * (crypto_int64) g1;
+ crypto_int64 f4g2 = f4 * (crypto_int64) g2;
+ crypto_int64 f4g3 = f4 * (crypto_int64) g3;
+ crypto_int64 f4g4 = f4 * (crypto_int64) g4;
+ crypto_int64 f4g5 = f4 * (crypto_int64) g5;
+ crypto_int64 f4g6_19 = f4 * (crypto_int64) g6_19;
+ crypto_int64 f4g7_19 = f4 * (crypto_int64) g7_19;
+ crypto_int64 f4g8_19 = f4 * (crypto_int64) g8_19;
+ crypto_int64 f4g9_19 = f4 * (crypto_int64) g9_19;
+ crypto_int64 f5g0 = f5 * (crypto_int64) g0;
+ crypto_int64 f5g1_2 = f5_2 * (crypto_int64) g1;
+ crypto_int64 f5g2 = f5 * (crypto_int64) g2;
+ crypto_int64 f5g3_2 = f5_2 * (crypto_int64) g3;
+ crypto_int64 f5g4 = f5 * (crypto_int64) g4;
+ crypto_int64 f5g5_38 = f5_2 * (crypto_int64) g5_19;
+ crypto_int64 f5g6_19 = f5 * (crypto_int64) g6_19;
+ crypto_int64 f5g7_38 = f5_2 * (crypto_int64) g7_19;
+ crypto_int64 f5g8_19 = f5 * (crypto_int64) g8_19;
+ crypto_int64 f5g9_38 = f5_2 * (crypto_int64) g9_19;
+ crypto_int64 f6g0 = f6 * (crypto_int64) g0;
+ crypto_int64 f6g1 = f6 * (crypto_int64) g1;
+ crypto_int64 f6g2 = f6 * (crypto_int64) g2;
+ crypto_int64 f6g3 = f6 * (crypto_int64) g3;
+ crypto_int64 f6g4_19 = f6 * (crypto_int64) g4_19;
+ crypto_int64 f6g5_19 = f6 * (crypto_int64) g5_19;
+ crypto_int64 f6g6_19 = f6 * (crypto_int64) g6_19;
+ crypto_int64 f6g7_19 = f6 * (crypto_int64) g7_19;
+ crypto_int64 f6g8_19 = f6 * (crypto_int64) g8_19;
+ crypto_int64 f6g9_19 = f6 * (crypto_int64) g9_19;
+ crypto_int64 f7g0 = f7 * (crypto_int64) g0;
+ crypto_int64 f7g1_2 = f7_2 * (crypto_int64) g1;
+ crypto_int64 f7g2 = f7 * (crypto_int64) g2;
+ crypto_int64 f7g3_38 = f7_2 * (crypto_int64) g3_19;
+ crypto_int64 f7g4_19 = f7 * (crypto_int64) g4_19;
+ crypto_int64 f7g5_38 = f7_2 * (crypto_int64) g5_19;
+ crypto_int64 f7g6_19 = f7 * (crypto_int64) g6_19;
+ crypto_int64 f7g7_38 = f7_2 * (crypto_int64) g7_19;
+ crypto_int64 f7g8_19 = f7 * (crypto_int64) g8_19;
+ crypto_int64 f7g9_38 = f7_2 * (crypto_int64) g9_19;
+ crypto_int64 f8g0 = f8 * (crypto_int64) g0;
+ crypto_int64 f8g1 = f8 * (crypto_int64) g1;
+ crypto_int64 f8g2_19 = f8 * (crypto_int64) g2_19;
+ crypto_int64 f8g3_19 = f8 * (crypto_int64) g3_19;
+ crypto_int64 f8g4_19 = f8 * (crypto_int64) g4_19;
+ crypto_int64 f8g5_19 = f8 * (crypto_int64) g5_19;
+ crypto_int64 f8g6_19 = f8 * (crypto_int64) g6_19;
+ crypto_int64 f8g7_19 = f8 * (crypto_int64) g7_19;
+ crypto_int64 f8g8_19 = f8 * (crypto_int64) g8_19;
+ crypto_int64 f8g9_19 = f8 * (crypto_int64) g9_19;
+ crypto_int64 f9g0 = f9 * (crypto_int64) g0;
+ crypto_int64 f9g1_38 = f9_2 * (crypto_int64) g1_19;
+ crypto_int64 f9g2_19 = f9 * (crypto_int64) g2_19;
+ crypto_int64 f9g3_38 = f9_2 * (crypto_int64) g3_19;
+ crypto_int64 f9g4_19 = f9 * (crypto_int64) g4_19;
+ crypto_int64 f9g5_38 = f9_2 * (crypto_int64) g5_19;
+ crypto_int64 f9g6_19 = f9 * (crypto_int64) g6_19;
+ crypto_int64 f9g7_38 = f9_2 * (crypto_int64) g7_19;
+ crypto_int64 f9g8_19 = f9 * (crypto_int64) g8_19;
+ crypto_int64 f9g9_38 = f9_2 * (crypto_int64) g9_19;
+ crypto_int64 h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38;
+ crypto_int64 h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19;
+ crypto_int64 h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38;
+ crypto_int64 h3 = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19;
+ crypto_int64 h4 = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38;
+ crypto_int64 h5 = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19;
+ crypto_int64 h6 = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38;
+ crypto_int64 h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19;
+ crypto_int64 h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38;
+ crypto_int64 h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ;
+ crypto_int64 carry0;
+ crypto_int64 carry1;
+ crypto_int64 carry2;
+ crypto_int64 carry3;
+ crypto_int64 carry4;
+ crypto_int64 carry5;
+ crypto_int64 carry6;
+ crypto_int64 carry7;
+ crypto_int64 carry8;
+ crypto_int64 carry9;
+
+ /*
+ |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38))
+ i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8
+ |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
+ i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9
+ */
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26);
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26);
+ /* |h0| <= 2^25 */
+ /* |h4| <= 2^25 */
+ /* |h1| <= 1.71*2^59 */
+ /* |h5| <= 1.71*2^59 */
+
+ carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= SHL64(carry1,25);
+ carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= SHL64(carry5,25);
+ /* |h1| <= 2^24; from now on fits into int32 */
+ /* |h5| <= 2^24; from now on fits into int32 */
+ /* |h2| <= 1.41*2^60 */
+ /* |h6| <= 1.41*2^60 */
+
+ carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= SHL64(carry2,26);
+ carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= SHL64(carry6,26);
+ /* |h2| <= 2^25; from now on fits into int32 unchanged */
+ /* |h6| <= 2^25; from now on fits into int32 unchanged */
+ /* |h3| <= 1.71*2^59 */
+ /* |h7| <= 1.71*2^59 */
+
+ carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= SHL64(carry3,25);
+ carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= SHL64(carry7,25);
+ /* |h3| <= 2^24; from now on fits into int32 unchanged */
+ /* |h7| <= 2^24; from now on fits into int32 unchanged */
+ /* |h4| <= 1.72*2^34 */
+ /* |h8| <= 1.41*2^60 */
+
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26);
+ carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= SHL64(carry8,26);
+ /* |h4| <= 2^25; from now on fits into int32 unchanged */
+ /* |h8| <= 2^25; from now on fits into int32 unchanged */
+ /* |h5| <= 1.01*2^24 */
+ /* |h9| <= 1.71*2^59 */
+
+ carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= SHL64(carry9,25);
+ /* |h9| <= 2^24; from now on fits into int32 unchanged */
+ /* |h0| <= 1.1*2^39 */
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26);
+ /* |h0| <= 2^25; from now on fits into int32 unchanged */
+ /* |h1| <= 1.01*2^24 */
+
+ h[0] = (crypto_int32) h0;
+ h[1] = (crypto_int32) h1;
+ h[2] = (crypto_int32) h2;
+ h[3] = (crypto_int32) h3;
+ h[4] = (crypto_int32) h4;
+ h[5] = (crypto_int32) h5;
+ h[6] = (crypto_int32) h6;
+ h[7] = (crypto_int32) h7;
+ h[8] = (crypto_int32) h8;
+ h[9] = (crypto_int32) h9;
+}
diff --git a/src/ext/ed25519/ref10/fe_neg.c b/src/ext/ed25519/ref10/fe_neg.c
new file mode 100644
index 0000000000..2078ce5284
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_neg.c
@@ -0,0 +1,45 @@
+#include "fe.h"
+
+/*
+h = -f
+
+Preconditions:
+ |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+
+Postconditions:
+ |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+*/
+
+void fe_neg(fe h,const fe f)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 h0 = -f0;
+ crypto_int32 h1 = -f1;
+ crypto_int32 h2 = -f2;
+ crypto_int32 h3 = -f3;
+ crypto_int32 h4 = -f4;
+ crypto_int32 h5 = -f5;
+ crypto_int32 h6 = -f6;
+ crypto_int32 h7 = -f7;
+ crypto_int32 h8 = -f8;
+ crypto_int32 h9 = -f9;
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
diff --git a/src/ext/ed25519/ref10/fe_pow22523.c b/src/ext/ed25519/ref10/fe_pow22523.c
new file mode 100644
index 0000000000..56675a5902
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_pow22523.c
@@ -0,0 +1,13 @@
+#include "fe.h"
+
+void fe_pow22523(fe out,const fe z)
+{
+ fe t0;
+ fe t1;
+ fe t2;
+ int i;
+
+#include "pow22523.h"
+
+ return;
+}
diff --git a/src/ext/ed25519/ref10/fe_sq.c b/src/ext/ed25519/ref10/fe_sq.c
new file mode 100644
index 0000000000..0022a17510
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_sq.c
@@ -0,0 +1,149 @@
+#include "fe.h"
+#include "crypto_int64.h"
+
+/*
+h = f * f
+Can overlap h with f.
+
+Preconditions:
+ |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+
+Postconditions:
+ |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+*/
+
+/*
+See fe_mul.c for discussion of implementation strategy.
+*/
+
+void fe_sq(fe h,const fe f)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 f0_2 = 2 * f0;
+ crypto_int32 f1_2 = 2 * f1;
+ crypto_int32 f2_2 = 2 * f2;
+ crypto_int32 f3_2 = 2 * f3;
+ crypto_int32 f4_2 = 2 * f4;
+ crypto_int32 f5_2 = 2 * f5;
+ crypto_int32 f6_2 = 2 * f6;
+ crypto_int32 f7_2 = 2 * f7;
+ crypto_int32 f5_38 = 38 * f5; /* 1.959375*2^30 */
+ crypto_int32 f6_19 = 19 * f6; /* 1.959375*2^30 */
+ crypto_int32 f7_38 = 38 * f7; /* 1.959375*2^30 */
+ crypto_int32 f8_19 = 19 * f8; /* 1.959375*2^30 */
+ crypto_int32 f9_38 = 38 * f9; /* 1.959375*2^30 */
+ crypto_int64 f0f0 = f0 * (crypto_int64) f0;
+ crypto_int64 f0f1_2 = f0_2 * (crypto_int64) f1;
+ crypto_int64 f0f2_2 = f0_2 * (crypto_int64) f2;
+ crypto_int64 f0f3_2 = f0_2 * (crypto_int64) f3;
+ crypto_int64 f0f4_2 = f0_2 * (crypto_int64) f4;
+ crypto_int64 f0f5_2 = f0_2 * (crypto_int64) f5;
+ crypto_int64 f0f6_2 = f0_2 * (crypto_int64) f6;
+ crypto_int64 f0f7_2 = f0_2 * (crypto_int64) f7;
+ crypto_int64 f0f8_2 = f0_2 * (crypto_int64) f8;
+ crypto_int64 f0f9_2 = f0_2 * (crypto_int64) f9;
+ crypto_int64 f1f1_2 = f1_2 * (crypto_int64) f1;
+ crypto_int64 f1f2_2 = f1_2 * (crypto_int64) f2;
+ crypto_int64 f1f3_4 = f1_2 * (crypto_int64) f3_2;
+ crypto_int64 f1f4_2 = f1_2 * (crypto_int64) f4;
+ crypto_int64 f1f5_4 = f1_2 * (crypto_int64) f5_2;
+ crypto_int64 f1f6_2 = f1_2 * (crypto_int64) f6;
+ crypto_int64 f1f7_4 = f1_2 * (crypto_int64) f7_2;
+ crypto_int64 f1f8_2 = f1_2 * (crypto_int64) f8;
+ crypto_int64 f1f9_76 = f1_2 * (crypto_int64) f9_38;
+ crypto_int64 f2f2 = f2 * (crypto_int64) f2;
+ crypto_int64 f2f3_2 = f2_2 * (crypto_int64) f3;
+ crypto_int64 f2f4_2 = f2_2 * (crypto_int64) f4;
+ crypto_int64 f2f5_2 = f2_2 * (crypto_int64) f5;
+ crypto_int64 f2f6_2 = f2_2 * (crypto_int64) f6;
+ crypto_int64 f2f7_2 = f2_2 * (crypto_int64) f7;
+ crypto_int64 f2f8_38 = f2_2 * (crypto_int64) f8_19;
+ crypto_int64 f2f9_38 = f2 * (crypto_int64) f9_38;
+ crypto_int64 f3f3_2 = f3_2 * (crypto_int64) f3;
+ crypto_int64 f3f4_2 = f3_2 * (crypto_int64) f4;
+ crypto_int64 f3f5_4 = f3_2 * (crypto_int64) f5_2;
+ crypto_int64 f3f6_2 = f3_2 * (crypto_int64) f6;
+ crypto_int64 f3f7_76 = f3_2 * (crypto_int64) f7_38;
+ crypto_int64 f3f8_38 = f3_2 * (crypto_int64) f8_19;
+ crypto_int64 f3f9_76 = f3_2 * (crypto_int64) f9_38;
+ crypto_int64 f4f4 = f4 * (crypto_int64) f4;
+ crypto_int64 f4f5_2 = f4_2 * (crypto_int64) f5;
+ crypto_int64 f4f6_38 = f4_2 * (crypto_int64) f6_19;
+ crypto_int64 f4f7_38 = f4 * (crypto_int64) f7_38;
+ crypto_int64 f4f8_38 = f4_2 * (crypto_int64) f8_19;
+ crypto_int64 f4f9_38 = f4 * (crypto_int64) f9_38;
+ crypto_int64 f5f5_38 = f5 * (crypto_int64) f5_38;
+ crypto_int64 f5f6_38 = f5_2 * (crypto_int64) f6_19;
+ crypto_int64 f5f7_76 = f5_2 * (crypto_int64) f7_38;
+ crypto_int64 f5f8_38 = f5_2 * (crypto_int64) f8_19;
+ crypto_int64 f5f9_76 = f5_2 * (crypto_int64) f9_38;
+ crypto_int64 f6f6_19 = f6 * (crypto_int64) f6_19;
+ crypto_int64 f6f7_38 = f6 * (crypto_int64) f7_38;
+ crypto_int64 f6f8_38 = f6_2 * (crypto_int64) f8_19;
+ crypto_int64 f6f9_38 = f6 * (crypto_int64) f9_38;
+ crypto_int64 f7f7_38 = f7 * (crypto_int64) f7_38;
+ crypto_int64 f7f8_38 = f7_2 * (crypto_int64) f8_19;
+ crypto_int64 f7f9_76 = f7_2 * (crypto_int64) f9_38;
+ crypto_int64 f8f8_19 = f8 * (crypto_int64) f8_19;
+ crypto_int64 f8f9_38 = f8 * (crypto_int64) f9_38;
+ crypto_int64 f9f9_38 = f9 * (crypto_int64) f9_38;
+ crypto_int64 h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;
+ crypto_int64 h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;
+ crypto_int64 h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19;
+ crypto_int64 h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38;
+ crypto_int64 h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38;
+ crypto_int64 h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38;
+ crypto_int64 h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19;
+ crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38;
+ crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38;
+ crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2;
+ crypto_int64 carry0;
+ crypto_int64 carry1;
+ crypto_int64 carry2;
+ crypto_int64 carry3;
+ crypto_int64 carry4;
+ crypto_int64 carry5;
+ crypto_int64 carry6;
+ crypto_int64 carry7;
+ crypto_int64 carry8;
+ crypto_int64 carry9;
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26);
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26);
+
+ carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= SHL64(carry1,25);
+ carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= SHL64(carry5,25);
+
+ carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= SHL64(carry2,26);
+ carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= SHL64(carry6,26);
+
+ carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= SHL64(carry3,25);
+ carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= SHL64(carry7,25);
+
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26);
+ carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= SHL64(carry8,26);
+
+ carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= SHL64(carry9,25);
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26);
+
+ h[0] = (crypto_int32) h0;
+ h[1] = (crypto_int32) h1;
+ h[2] = (crypto_int32) h2;
+ h[3] = (crypto_int32) h3;
+ h[4] = (crypto_int32) h4;
+ h[5] = (crypto_int32) h5;
+ h[6] = (crypto_int32) h6;
+ h[7] = (crypto_int32) h7;
+ h[8] = (crypto_int32) h8;
+ h[9] = (crypto_int32) h9;
+}
diff --git a/src/ext/ed25519/ref10/fe_sq2.c b/src/ext/ed25519/ref10/fe_sq2.c
new file mode 100644
index 0000000000..e8faa69ec9
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_sq2.c
@@ -0,0 +1,160 @@
+#include "fe.h"
+#include "crypto_int64.h"
+
+/*
+h = 2 * f * f
+Can overlap h with f.
+
+Preconditions:
+ |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+
+Postconditions:
+ |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+*/
+
+/*
+See fe_mul.c for discussion of implementation strategy.
+*/
+
+void fe_sq2(fe h,const fe f)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 f0_2 = 2 * f0;
+ crypto_int32 f1_2 = 2 * f1;
+ crypto_int32 f2_2 = 2 * f2;
+ crypto_int32 f3_2 = 2 * f3;
+ crypto_int32 f4_2 = 2 * f4;
+ crypto_int32 f5_2 = 2 * f5;
+ crypto_int32 f6_2 = 2 * f6;
+ crypto_int32 f7_2 = 2 * f7;
+ crypto_int32 f5_38 = 38 * f5; /* 1.959375*2^30 */
+ crypto_int32 f6_19 = 19 * f6; /* 1.959375*2^30 */
+ crypto_int32 f7_38 = 38 * f7; /* 1.959375*2^30 */
+ crypto_int32 f8_19 = 19 * f8; /* 1.959375*2^30 */
+ crypto_int32 f9_38 = 38 * f9; /* 1.959375*2^30 */
+ crypto_int64 f0f0 = f0 * (crypto_int64) f0;
+ crypto_int64 f0f1_2 = f0_2 * (crypto_int64) f1;
+ crypto_int64 f0f2_2 = f0_2 * (crypto_int64) f2;
+ crypto_int64 f0f3_2 = f0_2 * (crypto_int64) f3;
+ crypto_int64 f0f4_2 = f0_2 * (crypto_int64) f4;
+ crypto_int64 f0f5_2 = f0_2 * (crypto_int64) f5;
+ crypto_int64 f0f6_2 = f0_2 * (crypto_int64) f6;
+ crypto_int64 f0f7_2 = f0_2 * (crypto_int64) f7;
+ crypto_int64 f0f8_2 = f0_2 * (crypto_int64) f8;
+ crypto_int64 f0f9_2 = f0_2 * (crypto_int64) f9;
+ crypto_int64 f1f1_2 = f1_2 * (crypto_int64) f1;
+ crypto_int64 f1f2_2 = f1_2 * (crypto_int64) f2;
+ crypto_int64 f1f3_4 = f1_2 * (crypto_int64) f3_2;
+ crypto_int64 f1f4_2 = f1_2 * (crypto_int64) f4;
+ crypto_int64 f1f5_4 = f1_2 * (crypto_int64) f5_2;
+ crypto_int64 f1f6_2 = f1_2 * (crypto_int64) f6;
+ crypto_int64 f1f7_4 = f1_2 * (crypto_int64) f7_2;
+ crypto_int64 f1f8_2 = f1_2 * (crypto_int64) f8;
+ crypto_int64 f1f9_76 = f1_2 * (crypto_int64) f9_38;
+ crypto_int64 f2f2 = f2 * (crypto_int64) f2;
+ crypto_int64 f2f3_2 = f2_2 * (crypto_int64) f3;
+ crypto_int64 f2f4_2 = f2_2 * (crypto_int64) f4;
+ crypto_int64 f2f5_2 = f2_2 * (crypto_int64) f5;
+ crypto_int64 f2f6_2 = f2_2 * (crypto_int64) f6;
+ crypto_int64 f2f7_2 = f2_2 * (crypto_int64) f7;
+ crypto_int64 f2f8_38 = f2_2 * (crypto_int64) f8_19;
+ crypto_int64 f2f9_38 = f2 * (crypto_int64) f9_38;
+ crypto_int64 f3f3_2 = f3_2 * (crypto_int64) f3;
+ crypto_int64 f3f4_2 = f3_2 * (crypto_int64) f4;
+ crypto_int64 f3f5_4 = f3_2 * (crypto_int64) f5_2;
+ crypto_int64 f3f6_2 = f3_2 * (crypto_int64) f6;
+ crypto_int64 f3f7_76 = f3_2 * (crypto_int64) f7_38;
+ crypto_int64 f3f8_38 = f3_2 * (crypto_int64) f8_19;
+ crypto_int64 f3f9_76 = f3_2 * (crypto_int64) f9_38;
+ crypto_int64 f4f4 = f4 * (crypto_int64) f4;
+ crypto_int64 f4f5_2 = f4_2 * (crypto_int64) f5;
+ crypto_int64 f4f6_38 = f4_2 * (crypto_int64) f6_19;
+ crypto_int64 f4f7_38 = f4 * (crypto_int64) f7_38;
+ crypto_int64 f4f8_38 = f4_2 * (crypto_int64) f8_19;
+ crypto_int64 f4f9_38 = f4 * (crypto_int64) f9_38;
+ crypto_int64 f5f5_38 = f5 * (crypto_int64) f5_38;
+ crypto_int64 f5f6_38 = f5_2 * (crypto_int64) f6_19;
+ crypto_int64 f5f7_76 = f5_2 * (crypto_int64) f7_38;
+ crypto_int64 f5f8_38 = f5_2 * (crypto_int64) f8_19;
+ crypto_int64 f5f9_76 = f5_2 * (crypto_int64) f9_38;
+ crypto_int64 f6f6_19 = f6 * (crypto_int64) f6_19;
+ crypto_int64 f6f7_38 = f6 * (crypto_int64) f7_38;
+ crypto_int64 f6f8_38 = f6_2 * (crypto_int64) f8_19;
+ crypto_int64 f6f9_38 = f6 * (crypto_int64) f9_38;
+ crypto_int64 f7f7_38 = f7 * (crypto_int64) f7_38;
+ crypto_int64 f7f8_38 = f7_2 * (crypto_int64) f8_19;
+ crypto_int64 f7f9_76 = f7_2 * (crypto_int64) f9_38;
+ crypto_int64 f8f8_19 = f8 * (crypto_int64) f8_19;
+ crypto_int64 f8f9_38 = f8 * (crypto_int64) f9_38;
+ crypto_int64 f9f9_38 = f9 * (crypto_int64) f9_38;
+ crypto_int64 h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;
+ crypto_int64 h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;
+ crypto_int64 h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19;
+ crypto_int64 h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38;
+ crypto_int64 h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38;
+ crypto_int64 h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38;
+ crypto_int64 h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19;
+ crypto_int64 h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38;
+ crypto_int64 h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38;
+ crypto_int64 h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2;
+ crypto_int64 carry0;
+ crypto_int64 carry1;
+ crypto_int64 carry2;
+ crypto_int64 carry3;
+ crypto_int64 carry4;
+ crypto_int64 carry5;
+ crypto_int64 carry6;
+ crypto_int64 carry7;
+ crypto_int64 carry8;
+ crypto_int64 carry9;
+
+ h0 += h0;
+ h1 += h1;
+ h2 += h2;
+ h3 += h3;
+ h4 += h4;
+ h5 += h5;
+ h6 += h6;
+ h7 += h7;
+ h8 += h8;
+ h9 += h9;
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26);
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26);
+
+ carry1 = (h1 + (crypto_int64) (1<<24)) >> 25; h2 += carry1; h1 -= SHL64(carry1,25);
+ carry5 = (h5 + (crypto_int64) (1<<24)) >> 25; h6 += carry5; h5 -= SHL64(carry5,25);
+
+ carry2 = (h2 + (crypto_int64) (1<<25)) >> 26; h3 += carry2; h2 -= SHL64(carry2,26);
+ carry6 = (h6 + (crypto_int64) (1<<25)) >> 26; h7 += carry6; h6 -= SHL64(carry6,26);
+
+ carry3 = (h3 + (crypto_int64) (1<<24)) >> 25; h4 += carry3; h3 -= SHL64(carry3,25);
+ carry7 = (h7 + (crypto_int64) (1<<24)) >> 25; h8 += carry7; h7 -= SHL64(carry7,25);
+
+ carry4 = (h4 + (crypto_int64) (1<<25)) >> 26; h5 += carry4; h4 -= SHL64(carry4,26);
+ carry8 = (h8 + (crypto_int64) (1<<25)) >> 26; h9 += carry8; h8 -= SHL64(carry8,26);
+
+ carry9 = (h9 + (crypto_int64) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= SHL64(carry9,25);
+
+ carry0 = (h0 + (crypto_int64) (1<<25)) >> 26; h1 += carry0; h0 -= SHL64(carry0,26);
+
+ h[0] = (crypto_int32) h0;
+ h[1] = (crypto_int32) h1;
+ h[2] = (crypto_int32) h2;
+ h[3] = (crypto_int32) h3;
+ h[4] = (crypto_int32) h4;
+ h[5] = (crypto_int32) h5;
+ h[6] = (crypto_int32) h6;
+ h[7] = (crypto_int32) h7;
+ h[8] = (crypto_int32) h8;
+ h[9] = (crypto_int32) h9;
+}
diff --git a/src/ext/ed25519/ref10/fe_sub.c b/src/ext/ed25519/ref10/fe_sub.c
new file mode 100644
index 0000000000..6e26b7df8f
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_sub.c
@@ -0,0 +1,57 @@
+#include "fe.h"
+
+/*
+h = f - g
+Can overlap h with f or g.
+
+Preconditions:
+ |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+
+Postconditions:
+ |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+*/
+
+void fe_sub(fe h,const fe f,const fe g)
+{
+ crypto_int32 f0 = f[0];
+ crypto_int32 f1 = f[1];
+ crypto_int32 f2 = f[2];
+ crypto_int32 f3 = f[3];
+ crypto_int32 f4 = f[4];
+ crypto_int32 f5 = f[5];
+ crypto_int32 f6 = f[6];
+ crypto_int32 f7 = f[7];
+ crypto_int32 f8 = f[8];
+ crypto_int32 f9 = f[9];
+ crypto_int32 g0 = g[0];
+ crypto_int32 g1 = g[1];
+ crypto_int32 g2 = g[2];
+ crypto_int32 g3 = g[3];
+ crypto_int32 g4 = g[4];
+ crypto_int32 g5 = g[5];
+ crypto_int32 g6 = g[6];
+ crypto_int32 g7 = g[7];
+ crypto_int32 g8 = g[8];
+ crypto_int32 g9 = g[9];
+ crypto_int32 h0 = f0 - g0;
+ crypto_int32 h1 = f1 - g1;
+ crypto_int32 h2 = f2 - g2;
+ crypto_int32 h3 = f3 - g3;
+ crypto_int32 h4 = f4 - g4;
+ crypto_int32 h5 = f5 - g5;
+ crypto_int32 h6 = f6 - g6;
+ crypto_int32 h7 = f7 - g7;
+ crypto_int32 h8 = f8 - g8;
+ crypto_int32 h9 = f9 - g9;
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
diff --git a/src/ext/ed25519/ref10/fe_tobytes.c b/src/ext/ed25519/ref10/fe_tobytes.c
new file mode 100644
index 0000000000..3c7f389622
--- /dev/null
+++ b/src/ext/ed25519/ref10/fe_tobytes.c
@@ -0,0 +1,119 @@
+#include "fe.h"
+
+/*
+Preconditions:
+ |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+
+Write p=2^255-19; q=floor(h/p).
+Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
+
+Proof:
+ Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
+ Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4.
+
+ Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
+ Then 0<y<1.
+
+ Write r=h-pq.
+ Have 0<=r<=p-1=2^255-20.
+ Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
+
+ Write x=r+19(2^-255)r+y.
+ Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
+
+ Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
+ so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
+*/
+
+void fe_tobytes(unsigned char *s,const fe h)
+{
+ crypto_int32 h0 = h[0];
+ crypto_int32 h1 = h[1];
+ crypto_int32 h2 = h[2];
+ crypto_int32 h3 = h[3];
+ crypto_int32 h4 = h[4];
+ crypto_int32 h5 = h[5];
+ crypto_int32 h6 = h[6];
+ crypto_int32 h7 = h[7];
+ crypto_int32 h8 = h[8];
+ crypto_int32 h9 = h[9];
+ crypto_int32 q;
+ crypto_int32 carry0;
+ crypto_int32 carry1;
+ crypto_int32 carry2;
+ crypto_int32 carry3;
+ crypto_int32 carry4;
+ crypto_int32 carry5;
+ crypto_int32 carry6;
+ crypto_int32 carry7;
+ crypto_int32 carry8;
+ crypto_int32 carry9;
+
+ q = (19 * h9 + (((crypto_int32) 1) << 24)) >> 25;
+ q = (h0 + q) >> 26;
+ q = (h1 + q) >> 25;
+ q = (h2 + q) >> 26;
+ q = (h3 + q) >> 25;
+ q = (h4 + q) >> 26;
+ q = (h5 + q) >> 25;
+ q = (h6 + q) >> 26;
+ q = (h7 + q) >> 25;
+ q = (h8 + q) >> 26;
+ q = (h9 + q) >> 25;
+
+ /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
+ h0 += 19 * q;
+ /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
+
+ carry0 = h0 >> 26; h1 += carry0; h0 -= SHL32(carry0,26);
+ carry1 = h1 >> 25; h2 += carry1; h1 -= SHL32(carry1,25);
+ carry2 = h2 >> 26; h3 += carry2; h2 -= SHL32(carry2,26);
+ carry3 = h3 >> 25; h4 += carry3; h3 -= SHL32(carry3,25);
+ carry4 = h4 >> 26; h5 += carry4; h4 -= SHL32(carry4,26);
+ carry5 = h5 >> 25; h6 += carry5; h5 -= SHL32(carry5,25);
+ carry6 = h6 >> 26; h7 += carry6; h6 -= SHL32(carry6,26);
+ carry7 = h7 >> 25; h8 += carry7; h7 -= SHL32(carry7,25);
+ carry8 = h8 >> 26; h9 += carry8; h8 -= SHL32(carry8,26);
+ carry9 = h9 >> 25; h9 -= SHL32(carry9,25);
+ /* h10 = carry9 */
+
+ /*
+ Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
+ Have h0+...+2^230 h9 between 0 and 2^255-1;
+ evidently 2^255 h10-2^255 q = 0.
+ Goal: Output h0+...+2^230 h9.
+ */
+
+ s[0] = h0 >> 0;
+ s[1] = h0 >> 8;
+ s[2] = h0 >> 16;
+ s[3] = (h0 >> 24) | SHL32(h1,2);
+ s[4] = h1 >> 6;
+ s[5] = h1 >> 14;
+ s[6] = (h1 >> 22) | SHL32(h2,3);
+ s[7] = h2 >> 5;
+ s[8] = h2 >> 13;
+ s[9] = (h2 >> 21) | SHL32(h3,5);
+ s[10] = h3 >> 3;
+ s[11] = h3 >> 11;
+ s[12] = (h3 >> 19) | SHL32(h4,6);
+ s[13] = h4 >> 2;
+ s[14] = h4 >> 10;
+ s[15] = h4 >> 18;
+ s[16] = h5 >> 0;
+ s[17] = h5 >> 8;
+ s[18] = h5 >> 16;
+ s[19] = (h5 >> 24) | SHL32(h6,1);
+ s[20] = h6 >> 7;
+ s[21] = h6 >> 15;
+ s[22] = (h6 >> 23) | SHL32(h7,3);
+ s[23] = h7 >> 5;
+ s[24] = h7 >> 13;
+ s[25] = (h7 >> 21) | SHL32(h8,4);
+ s[26] = h8 >> 4;
+ s[27] = h8 >> 12;
+ s[28] = (h8 >> 20) | SHL32(h9,6);
+ s[29] = h9 >> 2;
+ s[30] = h9 >> 10;
+ s[31] = h9 >> 18;
+}
diff --git a/src/ext/ed25519/ref10/ge.h b/src/ext/ed25519/ref10/ge.h
new file mode 100644
index 0000000000..55e95f95b6
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge.h
@@ -0,0 +1,95 @@
+#ifndef GE_H
+#define GE_H
+
+/*
+ge means group element.
+
+Here the group is the set of pairs (x,y) of field elements (see fe.h)
+satisfying -x^2 + y^2 = 1 + d x^2y^2
+where d = -121665/121666.
+
+Representations:
+ ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
+ ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
+ ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
+ ge_precomp (Duif): (y+x,y-x,2dxy)
+*/
+
+#include "fe.h"
+
+typedef struct {
+ fe X;
+ fe Y;
+ fe Z;
+} ge_p2;
+
+typedef struct {
+ fe X;
+ fe Y;
+ fe Z;
+ fe T;
+} ge_p3;
+
+typedef struct {
+ fe X;
+ fe Y;
+ fe Z;
+ fe T;
+} ge_p1p1;
+
+typedef struct {
+ fe yplusx;
+ fe yminusx;
+ fe xy2d;
+} ge_precomp;
+
+typedef struct {
+ fe YplusX;
+ fe YminusX;
+ fe Z;
+ fe T2d;
+} ge_cached;
+
+#define ge_frombytes_negate_vartime crypto_sign_ed25519_ref10_ge_frombytes_negate_vartime
+#define ge_tobytes crypto_sign_ed25519_ref10_ge_tobytes
+#define ge_p3_tobytes crypto_sign_ed25519_ref10_ge_p3_tobytes
+
+#define ge_p2_0 crypto_sign_ed25519_ref10_ge_p2_0
+#define ge_p3_0 crypto_sign_ed25519_ref10_ge_p3_0
+#define ge_precomp_0 crypto_sign_ed25519_ref10_ge_precomp_0
+#define ge_p3_to_p2 crypto_sign_ed25519_ref10_ge_p3_to_p2
+#define ge_p3_to_cached crypto_sign_ed25519_ref10_ge_p3_to_cached
+#define ge_p1p1_to_p2 crypto_sign_ed25519_ref10_ge_p1p1_to_p2
+#define ge_p1p1_to_p3 crypto_sign_ed25519_ref10_ge_p1p1_to_p3
+#define ge_p2_dbl crypto_sign_ed25519_ref10_ge_p2_dbl
+#define ge_p3_dbl crypto_sign_ed25519_ref10_ge_p3_dbl
+
+#define ge_madd crypto_sign_ed25519_ref10_ge_madd
+#define ge_msub crypto_sign_ed25519_ref10_ge_msub
+#define ge_add crypto_sign_ed25519_ref10_ge_add
+#define ge_sub crypto_sign_ed25519_ref10_ge_sub
+#define ge_scalarmult_base crypto_sign_ed25519_ref10_ge_scalarmult_base
+#define ge_double_scalarmult_vartime crypto_sign_ed25519_ref10_ge_double_scalarmult_vartime
+
+extern void ge_tobytes(unsigned char *,const ge_p2 *);
+extern void ge_p3_tobytes(unsigned char *,const ge_p3 *);
+extern int ge_frombytes_negate_vartime(ge_p3 *,const unsigned char *);
+
+extern void ge_p2_0(ge_p2 *);
+extern void ge_p3_0(ge_p3 *);
+extern void ge_precomp_0(ge_precomp *);
+extern void ge_p3_to_p2(ge_p2 *,const ge_p3 *);
+extern void ge_p3_to_cached(ge_cached *,const ge_p3 *);
+extern void ge_p1p1_to_p2(ge_p2 *,const ge_p1p1 *);
+extern void ge_p1p1_to_p3(ge_p3 *,const ge_p1p1 *);
+extern void ge_p2_dbl(ge_p1p1 *,const ge_p2 *);
+extern void ge_p3_dbl(ge_p1p1 *,const ge_p3 *);
+
+extern void ge_madd(ge_p1p1 *,const ge_p3 *,const ge_precomp *);
+extern void ge_msub(ge_p1p1 *,const ge_p3 *,const ge_precomp *);
+extern void ge_add(ge_p1p1 *,const ge_p3 *,const ge_cached *);
+extern void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *);
+extern void ge_scalarmult_base(ge_p3 *,const unsigned char *);
+extern void ge_double_scalarmult_vartime(ge_p2 *,const unsigned char *,const ge_p3 *,const unsigned char *);
+
+#endif
diff --git a/src/ext/ed25519/ref10/ge_add.c b/src/ext/ed25519/ref10/ge_add.c
new file mode 100644
index 0000000000..da7ff5d2eb
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_add.c
@@ -0,0 +1,11 @@
+#include "ge.h"
+
+/*
+r = p + q
+*/
+
+void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q)
+{
+ fe t0;
+#include "ge_add.h"
+}
diff --git a/src/ext/ed25519/ref10/ge_add.h b/src/ext/ed25519/ref10/ge_add.h
new file mode 100644
index 0000000000..7481f8ffbe
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_add.h
@@ -0,0 +1,97 @@
+
+/* qhasm: enter ge_add */
+
+/* qhasm: fe X1 */
+
+/* qhasm: fe Y1 */
+
+/* qhasm: fe Z1 */
+
+/* qhasm: fe Z2 */
+
+/* qhasm: fe T1 */
+
+/* qhasm: fe ZZ */
+
+/* qhasm: fe YpX2 */
+
+/* qhasm: fe YmX2 */
+
+/* qhasm: fe T2d2 */
+
+/* qhasm: fe X3 */
+
+/* qhasm: fe Y3 */
+
+/* qhasm: fe Z3 */
+
+/* qhasm: fe T3 */
+
+/* qhasm: fe YpX1 */
+
+/* qhasm: fe YmX1 */
+
+/* qhasm: fe A */
+
+/* qhasm: fe B */
+
+/* qhasm: fe C */
+
+/* qhasm: fe D */
+
+/* qhasm: YpX1 = Y1+X1 */
+/* asm 1: fe_add(>YpX1=fe#1,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_add(>YpX1=r->X,<Y1=p->Y,<X1=p->X); */
+fe_add(r->X,p->Y,p->X);
+
+/* qhasm: YmX1 = Y1-X1 */
+/* asm 1: fe_sub(>YmX1=fe#2,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_sub(>YmX1=r->Y,<Y1=p->Y,<X1=p->X); */
+fe_sub(r->Y,p->Y,p->X);
+
+/* qhasm: A = YpX1*YpX2 */
+/* asm 1: fe_mul(>A=fe#3,<YpX1=fe#1,<YpX2=fe#15); */
+/* asm 2: fe_mul(>A=r->Z,<YpX1=r->X,<YpX2=q->YplusX); */
+fe_mul(r->Z,r->X,q->YplusX);
+
+/* qhasm: B = YmX1*YmX2 */
+/* asm 1: fe_mul(>B=fe#2,<YmX1=fe#2,<YmX2=fe#16); */
+/* asm 2: fe_mul(>B=r->Y,<YmX1=r->Y,<YmX2=q->YminusX); */
+fe_mul(r->Y,r->Y,q->YminusX);
+
+/* qhasm: C = T2d2*T1 */
+/* asm 1: fe_mul(>C=fe#4,<T2d2=fe#18,<T1=fe#14); */
+/* asm 2: fe_mul(>C=r->T,<T2d2=q->T2d,<T1=p->T); */
+fe_mul(r->T,q->T2d,p->T);
+
+/* qhasm: ZZ = Z1*Z2 */
+/* asm 1: fe_mul(>ZZ=fe#1,<Z1=fe#13,<Z2=fe#17); */
+/* asm 2: fe_mul(>ZZ=r->X,<Z1=p->Z,<Z2=q->Z); */
+fe_mul(r->X,p->Z,q->Z);
+
+/* qhasm: D = 2*ZZ */
+/* asm 1: fe_add(>D=fe#5,<ZZ=fe#1,<ZZ=fe#1); */
+/* asm 2: fe_add(>D=t0,<ZZ=r->X,<ZZ=r->X); */
+fe_add(t0,r->X,r->X);
+
+/* qhasm: X3 = A-B */
+/* asm 1: fe_sub(>X3=fe#1,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_sub(>X3=r->X,<A=r->Z,<B=r->Y); */
+fe_sub(r->X,r->Z,r->Y);
+
+/* qhasm: Y3 = A+B */
+/* asm 1: fe_add(>Y3=fe#2,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_add(>Y3=r->Y,<A=r->Z,<B=r->Y); */
+fe_add(r->Y,r->Z,r->Y);
+
+/* qhasm: Z3 = D+C */
+/* asm 1: fe_add(>Z3=fe#3,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_add(>Z3=r->Z,<D=t0,<C=r->T); */
+fe_add(r->Z,t0,r->T);
+
+/* qhasm: T3 = D-C */
+/* asm 1: fe_sub(>T3=fe#4,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_sub(>T3=r->T,<D=t0,<C=r->T); */
+fe_sub(r->T,t0,r->T);
+
+/* qhasm: return */
diff --git a/src/ext/ed25519/ref10/ge_add.q b/src/ext/ed25519/ref10/ge_add.q
new file mode 100644
index 0000000000..a6572ab0f8
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_add.q
@@ -0,0 +1,49 @@
+:name:fe:r->X:r->Y:r->Z:r->T:t0:t1:t2:t3:t4:t5:p->X:p->Y:p->Z:p->T:q->YplusX:q->YminusX:q->Z:q->T2d:
+fe r:var/r=fe:
+
+enter f:enter/f:>X1=fe#11:>Y1=fe#12:>Z1=fe#13:>T1=fe#14:>YpX2=fe#15:>YmX2=fe#16:>Z2=fe#17:>T2d2=fe#18:
+return:nofallthrough:<X3=fe#1:<Y3=fe#2:<Z3=fe#3:<T3=fe#4:leave:
+
+h=f+g:<f=fe:<g=fe:>h=fe:asm/fe_add(>h,<f,<g);:
+h=f-g:<f=fe:<g=fe:>h=fe:asm/fe_sub(>h,<f,<g);:
+h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);:
+h=f^2:<f=fe:>h=fe:asm/fe_sq(>h,<f);:
+h=2*g:<g=fe:>h=fe:asm/fe_add(>h,<g,<g);:
+
+:
+
+enter ge_add
+
+fe X1
+fe Y1
+fe Z1
+fe Z2
+fe T1
+fe ZZ
+fe YpX2
+fe YmX2
+fe T2d2
+fe X3
+fe Y3
+fe Z3
+fe T3
+fe YpX1
+fe YmX1
+fe A
+fe B
+fe C
+fe D
+
+YpX1 = Y1+X1
+YmX1 = Y1-X1
+A = YpX1*YpX2
+B = YmX1*YmX2
+C = T2d2*T1
+ZZ = Z1*Z2
+D = 2*ZZ
+X3 = A-B
+Y3 = A+B
+Z3 = D+C
+T3 = D-C
+
+return
diff --git a/src/ext/ed25519/ref10/ge_double_scalarmult.c b/src/ext/ed25519/ref10/ge_double_scalarmult.c
new file mode 100644
index 0000000000..f8bf4bf775
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_double_scalarmult.c
@@ -0,0 +1,96 @@
+#include "ge.h"
+
+static void slide(signed char *r,const unsigned char *a)
+{
+ int i;
+ int b;
+ int k;
+
+ for (i = 0;i < 256;++i)
+ r[i] = 1 & (a[i >> 3] >> (i & 7));
+
+ for (i = 0;i < 256;++i)
+ if (r[i]) {
+ for (b = 1;b <= 6 && i + b < 256;++b) {
+ if (r[i + b]) {
+ if (r[i] + (r[i + b] << b) <= 15) {
+ r[i] += r[i + b] << b; r[i + b] = 0;
+ } else if (r[i] - (r[i + b] << b) >= -15) {
+ r[i] -= r[i + b] << b;
+ for (k = i + b;k < 256;++k) {
+ if (!r[k]) {
+ r[k] = 1;
+ break;
+ }
+ r[k] = 0;
+ }
+ } else
+ break;
+ }
+ }
+ }
+
+}
+
+static ge_precomp Bi[8] = {
+#include "base2.h"
+} ;
+
+/*
+r = a * A + b * B
+where a = a[0]+256*a[1]+...+256^31 a[31].
+and b = b[0]+256*b[1]+...+256^31 b[31].
+B is the Ed25519 base point (x,4/5) with x positive.
+*/
+
+void ge_double_scalarmult_vartime(ge_p2 *r,const unsigned char *a,const ge_p3 *A,const unsigned char *b)
+{
+ signed char aslide[256];
+ signed char bslide[256];
+ ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
+ ge_p1p1 t;
+ ge_p3 u;
+ ge_p3 A2;
+ int i;
+
+ slide(aslide,a);
+ slide(bslide,b);
+
+ ge_p3_to_cached(&Ai[0],A);
+ ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t);
+ ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u);
+ ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u);
+ ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u);
+ ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u);
+ ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u);
+ ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u);
+ ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u);
+
+ ge_p2_0(r);
+
+ for (i = 255;i >= 0;--i) {
+ if (aslide[i] || bslide[i]) break;
+ }
+
+ for (;i >= 0;--i) {
+ ge_p2_dbl(&t,r);
+
+ if (aslide[i] > 0) {
+ ge_p1p1_to_p3(&u,&t);
+ ge_add(&t,&u,&Ai[aslide[i]/2]);
+ } else if (aslide[i] < 0) {
+ ge_p1p1_to_p3(&u,&t);
+ ge_sub(&t,&u,&Ai[(-aslide[i])/2]);
+ }
+
+ if (bslide[i] > 0) {
+ ge_p1p1_to_p3(&u,&t);
+ ge_madd(&t,&u,&Bi[bslide[i]/2]);
+ } else if (bslide[i] < 0) {
+ ge_p1p1_to_p3(&u,&t);
+ ge_msub(&t,&u,&Bi[(-bslide[i])/2]);
+ }
+
+ ge_p1p1_to_p2(r,&t);
+ }
+}
diff --git a/src/ext/ed25519/ref10/ge_frombytes.c b/src/ext/ed25519/ref10/ge_frombytes.c
new file mode 100644
index 0000000000..1a059ee93f
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_frombytes.c
@@ -0,0 +1,50 @@
+#include "ge.h"
+
+static const fe d = {
+#include "d.h"
+} ;
+
+static const fe sqrtm1 = {
+#include "sqrtm1.h"
+} ;
+
+int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s)
+{
+ fe u;
+ fe v;
+ fe v3;
+ fe vxx;
+ fe check;
+
+ fe_frombytes(h->Y,s);
+ fe_1(h->Z);
+ fe_sq(u,h->Y);
+ fe_mul(v,u,d);
+ fe_sub(u,u,h->Z); /* u = y^2-1 */
+ fe_add(v,v,h->Z); /* v = dy^2+1 */
+
+ fe_sq(v3,v);
+ fe_mul(v3,v3,v); /* v3 = v^3 */
+ fe_sq(h->X,v3);
+ fe_mul(h->X,h->X,v);
+ fe_mul(h->X,h->X,u); /* x = uv^7 */
+
+ fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */
+ fe_mul(h->X,h->X,v3);
+ fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */
+
+ fe_sq(vxx,h->X);
+ fe_mul(vxx,vxx,v);
+ fe_sub(check,vxx,u); /* vx^2-u */
+ if (fe_isnonzero(check)) {
+ fe_add(check,vxx,u); /* vx^2+u */
+ if (fe_isnonzero(check)) return -1;
+ fe_mul(h->X,h->X,sqrtm1);
+ }
+
+ if (fe_isnegative(h->X) == (s[31] >> 7))
+ fe_neg(h->X,h->X);
+
+ fe_mul(h->T,h->X,h->Y);
+ return 0;
+}
diff --git a/src/ext/ed25519/ref10/ge_madd.c b/src/ext/ed25519/ref10/ge_madd.c
new file mode 100644
index 0000000000..622571774b
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_madd.c
@@ -0,0 +1,11 @@
+#include "ge.h"
+
+/*
+r = p + q
+*/
+
+void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q)
+{
+ fe t0;
+#include "ge_madd.h"
+}
diff --git a/src/ext/ed25519/ref10/ge_madd.h b/src/ext/ed25519/ref10/ge_madd.h
new file mode 100644
index 0000000000..ecae84952b
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_madd.h
@@ -0,0 +1,88 @@
+
+/* qhasm: enter ge_madd */
+
+/* qhasm: fe X1 */
+
+/* qhasm: fe Y1 */
+
+/* qhasm: fe Z1 */
+
+/* qhasm: fe T1 */
+
+/* qhasm: fe ypx2 */
+
+/* qhasm: fe ymx2 */
+
+/* qhasm: fe xy2d2 */
+
+/* qhasm: fe X3 */
+
+/* qhasm: fe Y3 */
+
+/* qhasm: fe Z3 */
+
+/* qhasm: fe T3 */
+
+/* qhasm: fe YpX1 */
+
+/* qhasm: fe YmX1 */
+
+/* qhasm: fe A */
+
+/* qhasm: fe B */
+
+/* qhasm: fe C */
+
+/* qhasm: fe D */
+
+/* qhasm: YpX1 = Y1+X1 */
+/* asm 1: fe_add(>YpX1=fe#1,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_add(>YpX1=r->X,<Y1=p->Y,<X1=p->X); */
+fe_add(r->X,p->Y,p->X);
+
+/* qhasm: YmX1 = Y1-X1 */
+/* asm 1: fe_sub(>YmX1=fe#2,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_sub(>YmX1=r->Y,<Y1=p->Y,<X1=p->X); */
+fe_sub(r->Y,p->Y,p->X);
+
+/* qhasm: A = YpX1*ypx2 */
+/* asm 1: fe_mul(>A=fe#3,<YpX1=fe#1,<ypx2=fe#15); */
+/* asm 2: fe_mul(>A=r->Z,<YpX1=r->X,<ypx2=q->yplusx); */
+fe_mul(r->Z,r->X,q->yplusx);
+
+/* qhasm: B = YmX1*ymx2 */
+/* asm 1: fe_mul(>B=fe#2,<YmX1=fe#2,<ymx2=fe#16); */
+/* asm 2: fe_mul(>B=r->Y,<YmX1=r->Y,<ymx2=q->yminusx); */
+fe_mul(r->Y,r->Y,q->yminusx);
+
+/* qhasm: C = xy2d2*T1 */
+/* asm 1: fe_mul(>C=fe#4,<xy2d2=fe#17,<T1=fe#14); */
+/* asm 2: fe_mul(>C=r->T,<xy2d2=q->xy2d,<T1=p->T); */
+fe_mul(r->T,q->xy2d,p->T);
+
+/* qhasm: D = 2*Z1 */
+/* asm 1: fe_add(>D=fe#5,<Z1=fe#13,<Z1=fe#13); */
+/* asm 2: fe_add(>D=t0,<Z1=p->Z,<Z1=p->Z); */
+fe_add(t0,p->Z,p->Z);
+
+/* qhasm: X3 = A-B */
+/* asm 1: fe_sub(>X3=fe#1,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_sub(>X3=r->X,<A=r->Z,<B=r->Y); */
+fe_sub(r->X,r->Z,r->Y);
+
+/* qhasm: Y3 = A+B */
+/* asm 1: fe_add(>Y3=fe#2,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_add(>Y3=r->Y,<A=r->Z,<B=r->Y); */
+fe_add(r->Y,r->Z,r->Y);
+
+/* qhasm: Z3 = D+C */
+/* asm 1: fe_add(>Z3=fe#3,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_add(>Z3=r->Z,<D=t0,<C=r->T); */
+fe_add(r->Z,t0,r->T);
+
+/* qhasm: T3 = D-C */
+/* asm 1: fe_sub(>T3=fe#4,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_sub(>T3=r->T,<D=t0,<C=r->T); */
+fe_sub(r->T,t0,r->T);
+
+/* qhasm: return */
diff --git a/src/ext/ed25519/ref10/ge_madd.q b/src/ext/ed25519/ref10/ge_madd.q
new file mode 100644
index 0000000000..aa3db454e6
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_madd.q
@@ -0,0 +1,46 @@
+:name:fe:r->X:r->Y:r->Z:r->T:t0:t1:t2:t3:t4:t5:p->X:p->Y:p->Z:p->T:q->yplusx:q->yminusx:q->xy2d:
+fe r:var/r=fe:
+
+enter f:enter/f:>X1=fe#11:>Y1=fe#12:>Z1=fe#13:>T1=fe#14:>ypx2=fe#15:>ymx2=fe#16:>xy2d2=fe#17:
+return:nofallthrough:<X3=fe#1:<Y3=fe#2:<Z3=fe#3:<T3=fe#4:leave:
+
+h=f+g:<f=fe:<g=fe:>h=fe:asm/fe_add(>h,<f,<g);:
+h=f-g:<f=fe:<g=fe:>h=fe:asm/fe_sub(>h,<f,<g);:
+h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);:
+h=f^2:<f=fe:>h=fe:asm/fe_sq(>h,<f);:
+h=2*g:<g=fe:>h=fe:asm/fe_add(>h,<g,<g);:
+
+:
+
+enter ge_madd
+
+fe X1
+fe Y1
+fe Z1
+fe T1
+fe ypx2
+fe ymx2
+fe xy2d2
+fe X3
+fe Y3
+fe Z3
+fe T3
+fe YpX1
+fe YmX1
+fe A
+fe B
+fe C
+fe D
+
+YpX1 = Y1+X1
+YmX1 = Y1-X1
+A = YpX1*ypx2
+B = YmX1*ymx2
+C = xy2d2*T1
+D = 2*Z1
+X3 = A-B
+Y3 = A+B
+Z3 = D+C
+T3 = D-C
+
+return
diff --git a/src/ext/ed25519/ref10/ge_msub.c b/src/ext/ed25519/ref10/ge_msub.c
new file mode 100644
index 0000000000..741ecbf113
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_msub.c
@@ -0,0 +1,11 @@
+#include "ge.h"
+
+/*
+r = p - q
+*/
+
+void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q)
+{
+ fe t0;
+#include "ge_msub.h"
+}
diff --git a/src/ext/ed25519/ref10/ge_msub.h b/src/ext/ed25519/ref10/ge_msub.h
new file mode 100644
index 0000000000..500f986ba0
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_msub.h
@@ -0,0 +1,88 @@
+
+/* qhasm: enter ge_msub */
+
+/* qhasm: fe X1 */
+
+/* qhasm: fe Y1 */
+
+/* qhasm: fe Z1 */
+
+/* qhasm: fe T1 */
+
+/* qhasm: fe ypx2 */
+
+/* qhasm: fe ymx2 */
+
+/* qhasm: fe xy2d2 */
+
+/* qhasm: fe X3 */
+
+/* qhasm: fe Y3 */
+
+/* qhasm: fe Z3 */
+
+/* qhasm: fe T3 */
+
+/* qhasm: fe YpX1 */
+
+/* qhasm: fe YmX1 */
+
+/* qhasm: fe A */
+
+/* qhasm: fe B */
+
+/* qhasm: fe C */
+
+/* qhasm: fe D */
+
+/* qhasm: YpX1 = Y1+X1 */
+/* asm 1: fe_add(>YpX1=fe#1,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_add(>YpX1=r->X,<Y1=p->Y,<X1=p->X); */
+fe_add(r->X,p->Y,p->X);
+
+/* qhasm: YmX1 = Y1-X1 */
+/* asm 1: fe_sub(>YmX1=fe#2,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_sub(>YmX1=r->Y,<Y1=p->Y,<X1=p->X); */
+fe_sub(r->Y,p->Y,p->X);
+
+/* qhasm: A = YpX1*ymx2 */
+/* asm 1: fe_mul(>A=fe#3,<YpX1=fe#1,<ymx2=fe#16); */
+/* asm 2: fe_mul(>A=r->Z,<YpX1=r->X,<ymx2=q->yminusx); */
+fe_mul(r->Z,r->X,q->yminusx);
+
+/* qhasm: B = YmX1*ypx2 */
+/* asm 1: fe_mul(>B=fe#2,<YmX1=fe#2,<ypx2=fe#15); */
+/* asm 2: fe_mul(>B=r->Y,<YmX1=r->Y,<ypx2=q->yplusx); */
+fe_mul(r->Y,r->Y,q->yplusx);
+
+/* qhasm: C = xy2d2*T1 */
+/* asm 1: fe_mul(>C=fe#4,<xy2d2=fe#17,<T1=fe#14); */
+/* asm 2: fe_mul(>C=r->T,<xy2d2=q->xy2d,<T1=p->T); */
+fe_mul(r->T,q->xy2d,p->T);
+
+/* qhasm: D = 2*Z1 */
+/* asm 1: fe_add(>D=fe#5,<Z1=fe#13,<Z1=fe#13); */
+/* asm 2: fe_add(>D=t0,<Z1=p->Z,<Z1=p->Z); */
+fe_add(t0,p->Z,p->Z);
+
+/* qhasm: X3 = A-B */
+/* asm 1: fe_sub(>X3=fe#1,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_sub(>X3=r->X,<A=r->Z,<B=r->Y); */
+fe_sub(r->X,r->Z,r->Y);
+
+/* qhasm: Y3 = A+B */
+/* asm 1: fe_add(>Y3=fe#2,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_add(>Y3=r->Y,<A=r->Z,<B=r->Y); */
+fe_add(r->Y,r->Z,r->Y);
+
+/* qhasm: Z3 = D-C */
+/* asm 1: fe_sub(>Z3=fe#3,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_sub(>Z3=r->Z,<D=t0,<C=r->T); */
+fe_sub(r->Z,t0,r->T);
+
+/* qhasm: T3 = D+C */
+/* asm 1: fe_add(>T3=fe#4,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_add(>T3=r->T,<D=t0,<C=r->T); */
+fe_add(r->T,t0,r->T);
+
+/* qhasm: return */
diff --git a/src/ext/ed25519/ref10/ge_msub.q b/src/ext/ed25519/ref10/ge_msub.q
new file mode 100644
index 0000000000..e3cadd882d
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_msub.q
@@ -0,0 +1,46 @@
+:name:fe:r->X:r->Y:r->Z:r->T:t0:t1:t2:t3:t4:t5:p->X:p->Y:p->Z:p->T:q->yplusx:q->yminusx:q->xy2d:
+fe r:var/r=fe:
+
+enter f:enter/f:>X1=fe#11:>Y1=fe#12:>Z1=fe#13:>T1=fe#14:>ypx2=fe#15:>ymx2=fe#16:>xy2d2=fe#17:
+return:nofallthrough:<X3=fe#1:<Y3=fe#2:<Z3=fe#3:<T3=fe#4:leave:
+
+h=f+g:<f=fe:<g=fe:>h=fe:asm/fe_add(>h,<f,<g);:
+h=f-g:<f=fe:<g=fe:>h=fe:asm/fe_sub(>h,<f,<g);:
+h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);:
+h=f^2:<f=fe:>h=fe:asm/fe_sq(>h,<f);:
+h=2*g:<g=fe:>h=fe:asm/fe_add(>h,<g,<g);:
+
+:
+
+enter ge_msub
+
+fe X1
+fe Y1
+fe Z1
+fe T1
+fe ypx2
+fe ymx2
+fe xy2d2
+fe X3
+fe Y3
+fe Z3
+fe T3
+fe YpX1
+fe YmX1
+fe A
+fe B
+fe C
+fe D
+
+YpX1 = Y1+X1
+YmX1 = Y1-X1
+A = YpX1*ymx2
+B = YmX1*ypx2
+C = xy2d2*T1
+D = 2*Z1
+X3 = A-B
+Y3 = A+B
+Z3 = D-C
+T3 = D+C
+
+return
diff --git a/src/ext/ed25519/ref10/ge_p1p1_to_p2.c b/src/ext/ed25519/ref10/ge_p1p1_to_p2.c
new file mode 100644
index 0000000000..9bb5013d66
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_p1p1_to_p2.c
@@ -0,0 +1,12 @@
+#include "ge.h"
+
+/*
+r = p
+*/
+
+extern void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p)
+{
+ fe_mul(r->X,p->X,p->T);
+ fe_mul(r->Y,p->Y,p->Z);
+ fe_mul(r->Z,p->Z,p->T);
+}
diff --git a/src/ext/ed25519/ref10/ge_p1p1_to_p3.c b/src/ext/ed25519/ref10/ge_p1p1_to_p3.c
new file mode 100644
index 0000000000..2f57b10968
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_p1p1_to_p3.c
@@ -0,0 +1,13 @@
+#include "ge.h"
+
+/*
+r = p
+*/
+
+extern void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p)
+{
+ fe_mul(r->X,p->X,p->T);
+ fe_mul(r->Y,p->Y,p->Z);
+ fe_mul(r->Z,p->Z,p->T);
+ fe_mul(r->T,p->X,p->Y);
+}
diff --git a/src/ext/ed25519/ref10/ge_p2_0.c b/src/ext/ed25519/ref10/ge_p2_0.c
new file mode 100644
index 0000000000..6191d1e6e4
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_p2_0.c
@@ -0,0 +1,8 @@
+#include "ge.h"
+
+void ge_p2_0(ge_p2 *h)
+{
+ fe_0(h->X);
+ fe_1(h->Y);
+ fe_1(h->Z);
+}
diff --git a/src/ext/ed25519/ref10/ge_p2_dbl.c b/src/ext/ed25519/ref10/ge_p2_dbl.c
new file mode 100644
index 0000000000..2e332b5cee
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_p2_dbl.c
@@ -0,0 +1,11 @@
+#include "ge.h"
+
+/*
+r = 2 * p
+*/
+
+void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p)
+{
+ fe t0;
+#include "ge_p2_dbl.h"
+}
diff --git a/src/ext/ed25519/ref10/ge_p2_dbl.h b/src/ext/ed25519/ref10/ge_p2_dbl.h
new file mode 100644
index 0000000000..128efed907
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_p2_dbl.h
@@ -0,0 +1,73 @@
+
+/* qhasm: enter ge_p2_dbl */
+
+/* qhasm: fe X1 */
+
+/* qhasm: fe Y1 */
+
+/* qhasm: fe Z1 */
+
+/* qhasm: fe A */
+
+/* qhasm: fe AA */
+
+/* qhasm: fe XX */
+
+/* qhasm: fe YY */
+
+/* qhasm: fe B */
+
+/* qhasm: fe X3 */
+
+/* qhasm: fe Y3 */
+
+/* qhasm: fe Z3 */
+
+/* qhasm: fe T3 */
+
+/* qhasm: XX=X1^2 */
+/* asm 1: fe_sq(>XX=fe#1,<X1=fe#11); */
+/* asm 2: fe_sq(>XX=r->X,<X1=p->X); */
+fe_sq(r->X,p->X);
+
+/* qhasm: YY=Y1^2 */
+/* asm 1: fe_sq(>YY=fe#3,<Y1=fe#12); */
+/* asm 2: fe_sq(>YY=r->Z,<Y1=p->Y); */
+fe_sq(r->Z,p->Y);
+
+/* qhasm: B=2*Z1^2 */
+/* asm 1: fe_sq2(>B=fe#4,<Z1=fe#13); */
+/* asm 2: fe_sq2(>B=r->T,<Z1=p->Z); */
+fe_sq2(r->T,p->Z);
+
+/* qhasm: A=X1+Y1 */
+/* asm 1: fe_add(>A=fe#2,<X1=fe#11,<Y1=fe#12); */
+/* asm 2: fe_add(>A=r->Y,<X1=p->X,<Y1=p->Y); */
+fe_add(r->Y,p->X,p->Y);
+
+/* qhasm: AA=A^2 */
+/* asm 1: fe_sq(>AA=fe#5,<A=fe#2); */
+/* asm 2: fe_sq(>AA=t0,<A=r->Y); */
+fe_sq(t0,r->Y);
+
+/* qhasm: Y3=YY+XX */
+/* asm 1: fe_add(>Y3=fe#2,<YY=fe#3,<XX=fe#1); */
+/* asm 2: fe_add(>Y3=r->Y,<YY=r->Z,<XX=r->X); */
+fe_add(r->Y,r->Z,r->X);
+
+/* qhasm: Z3=YY-XX */
+/* asm 1: fe_sub(>Z3=fe#3,<YY=fe#3,<XX=fe#1); */
+/* asm 2: fe_sub(>Z3=r->Z,<YY=r->Z,<XX=r->X); */
+fe_sub(r->Z,r->Z,r->X);
+
+/* qhasm: X3=AA-Y3 */
+/* asm 1: fe_sub(>X3=fe#1,<AA=fe#5,<Y3=fe#2); */
+/* asm 2: fe_sub(>X3=r->X,<AA=t0,<Y3=r->Y); */
+fe_sub(r->X,t0,r->Y);
+
+/* qhasm: T3=B-Z3 */
+/* asm 1: fe_sub(>T3=fe#4,<B=fe#4,<Z3=fe#3); */
+/* asm 2: fe_sub(>T3=r->T,<B=r->T,<Z3=r->Z); */
+fe_sub(r->T,r->T,r->Z);
+
+/* qhasm: return */
diff --git a/src/ext/ed25519/ref10/ge_p2_dbl.q b/src/ext/ed25519/ref10/ge_p2_dbl.q
new file mode 100644
index 0000000000..170d42f9a7
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_p2_dbl.q
@@ -0,0 +1,41 @@
+:name:fe:r->X:r->Y:r->Z:r->T:t0:t1:t2:t3:t4:t5:p->X:p->Y:p->Z:
+fe r:var/r=fe:
+
+enter f:enter/f:>X1=fe#11:>Y1=fe#12:>Z1=fe#13:
+return:nofallthrough:<X3=fe#1:<Y3=fe#2:<Z3=fe#3:<T3=fe#4:leave:
+
+h=f+g:<f=fe:<g=fe:>h=fe:asm/fe_add(>h,<f,<g);:
+h=f-g:<f=fe:<g=fe:>h=fe:asm/fe_sub(>h,<f,<g);:
+h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);:
+h=f^2:<f=fe:>h=fe:asm/fe_sq(>h,<f);:
+h=2*f^2:<f=fe:>h=fe:asm/fe_sq2(>h,<f);:
+h=2*g:<g=fe:>h=fe:asm/fe_add(>h,<g,<g);:
+
+:
+
+enter ge_p2_dbl
+
+fe X1
+fe Y1
+fe Z1
+fe A
+fe AA
+fe XX
+fe YY
+fe B
+fe X3
+fe Y3
+fe Z3
+fe T3
+
+XX=X1^2
+YY=Y1^2
+B=2*Z1^2
+A=X1+Y1
+AA=A^2
+Y3=YY+XX
+Z3=YY-XX
+X3=AA-Y3
+T3=B-Z3
+
+return
diff --git a/src/ext/ed25519/ref10/ge_p3_0.c b/src/ext/ed25519/ref10/ge_p3_0.c
new file mode 100644
index 0000000000..401b2935a1
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_p3_0.c
@@ -0,0 +1,9 @@
+#include "ge.h"
+
+void ge_p3_0(ge_p3 *h)
+{
+ fe_0(h->X);
+ fe_1(h->Y);
+ fe_1(h->Z);
+ fe_0(h->T);
+}
diff --git a/src/ext/ed25519/ref10/ge_p3_dbl.c b/src/ext/ed25519/ref10/ge_p3_dbl.c
new file mode 100644
index 0000000000..0d8a05915d
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_p3_dbl.c
@@ -0,0 +1,12 @@
+#include "ge.h"
+
+/*
+r = 2 * p
+*/
+
+void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p)
+{
+ ge_p2 q;
+ ge_p3_to_p2(&q,p);
+ ge_p2_dbl(r,&q);
+}
diff --git a/src/ext/ed25519/ref10/ge_p3_to_cached.c b/src/ext/ed25519/ref10/ge_p3_to_cached.c
new file mode 100644
index 0000000000..bde64228cf
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_p3_to_cached.c
@@ -0,0 +1,17 @@
+#include "ge.h"
+
+/*
+r = p
+*/
+
+static const fe d2 = {
+#include "d2.h"
+} ;
+
+extern void ge_p3_to_cached(ge_cached *r,const ge_p3 *p)
+{
+ fe_add(r->YplusX,p->Y,p->X);
+ fe_sub(r->YminusX,p->Y,p->X);
+ fe_copy(r->Z,p->Z);
+ fe_mul(r->T2d,p->T,d2);
+}
diff --git a/src/ext/ed25519/ref10/ge_p3_to_p2.c b/src/ext/ed25519/ref10/ge_p3_to_p2.c
new file mode 100644
index 0000000000..e532a9e4cb
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_p3_to_p2.c
@@ -0,0 +1,12 @@
+#include "ge.h"
+
+/*
+r = p
+*/
+
+extern void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p)
+{
+ fe_copy(r->X,p->X);
+ fe_copy(r->Y,p->Y);
+ fe_copy(r->Z,p->Z);
+}
diff --git a/src/ext/ed25519/ref10/ge_p3_tobytes.c b/src/ext/ed25519/ref10/ge_p3_tobytes.c
new file mode 100644
index 0000000000..21cb2fc656
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_p3_tobytes.c
@@ -0,0 +1,14 @@
+#include "ge.h"
+
+void ge_p3_tobytes(unsigned char *s,const ge_p3 *h)
+{
+ fe recip;
+ fe x;
+ fe y;
+
+ fe_invert(recip,h->Z);
+ fe_mul(x,h->X,recip);
+ fe_mul(y,h->Y,recip);
+ fe_tobytes(s,y);
+ s[31] ^= fe_isnegative(x) << 7;
+}
diff --git a/src/ext/ed25519/ref10/ge_precomp_0.c b/src/ext/ed25519/ref10/ge_precomp_0.c
new file mode 100644
index 0000000000..2e218861d8
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_precomp_0.c
@@ -0,0 +1,8 @@
+#include "ge.h"
+
+void ge_precomp_0(ge_precomp *h)
+{
+ fe_1(h->yplusx);
+ fe_1(h->yminusx);
+ fe_0(h->xy2d);
+}
diff --git a/src/ext/ed25519/ref10/ge_scalarmult_base.c b/src/ext/ed25519/ref10/ge_scalarmult_base.c
new file mode 100644
index 0000000000..5292f83221
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_scalarmult_base.c
@@ -0,0 +1,109 @@
+#include "ge.h"
+#include "crypto_uint32.h"
+
+/* Rename this so as not to interfere with select() which torint.h apparently
+ * grabs. :p */
+#define select ed25519_ref10_select
+
+static unsigned char equal(signed char b,signed char c)
+{
+ unsigned char ub = b;
+ unsigned char uc = c;
+ unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
+ crypto_uint32 y = x; /* 0: yes; 1..255: no */
+ y -= 1; /* 4294967295: yes; 0..254: no */
+ y >>= 31; /* 1: yes; 0: no */
+ return y;
+}
+
+static unsigned char negative(signed char b)
+{
+ uint64_t x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
+ x >>= 63; /* 1: yes; 0: no */
+ return x;
+}
+
+static void cmov(ge_precomp *t,ge_precomp *u,unsigned char b)
+{
+ fe_cmov(t->yplusx,u->yplusx,b);
+ fe_cmov(t->yminusx,u->yminusx,b);
+ fe_cmov(t->xy2d,u->xy2d,b);
+}
+
+/* base[i][j] = (j+1)*256^i*B */
+static ge_precomp base[32][8] = {
+#include "base.h"
+} ;
+
+static void select(ge_precomp *t,int pos,signed char b)
+{
+ ge_precomp minust;
+ unsigned char bnegative = negative(b);
+ unsigned char babs = b - SHL8( (-bnegative) & (unsigned char)b, 1);
+
+ ge_precomp_0(t);
+ cmov(t,&base[pos][0],equal(babs,1));
+ cmov(t,&base[pos][1],equal(babs,2));
+ cmov(t,&base[pos][2],equal(babs,3));
+ cmov(t,&base[pos][3],equal(babs,4));
+ cmov(t,&base[pos][4],equal(babs,5));
+ cmov(t,&base[pos][5],equal(babs,6));
+ cmov(t,&base[pos][6],equal(babs,7));
+ cmov(t,&base[pos][7],equal(babs,8));
+ fe_copy(minust.yplusx,t->yminusx);
+ fe_copy(minust.yminusx,t->yplusx);
+ fe_neg(minust.xy2d,t->xy2d);
+ cmov(t,&minust,bnegative);
+}
+
+/*
+h = a * B
+where a = a[0]+256*a[1]+...+256^31 a[31]
+B is the Ed25519 base point (x,4/5) with x positive.
+
+Preconditions:
+ a[31] <= 127
+*/
+
+void ge_scalarmult_base(ge_p3 *h,const unsigned char *a)
+{
+ signed char e[64];
+ signed char carry;
+ ge_p1p1 r;
+ ge_p2 s;
+ ge_precomp t;
+ int i;
+
+ for (i = 0;i < 32;++i) {
+ e[2 * i + 0] = (a[i] >> 0) & 15;
+ e[2 * i + 1] = (a[i] >> 4) & 15;
+ }
+ /* each e[i] is between 0 and 15 */
+ /* e[63] is between 0 and 7 */
+
+ carry = 0;
+ for (i = 0;i < 63;++i) {
+ e[i] += carry;
+ carry = e[i] + 8;
+ carry >>= 4;
+ e[i] -= SHL8(carry,4);
+ }
+ e[63] += carry;
+ /* each e[i] is between -8 and 8 */
+
+ ge_p3_0(h);
+ for (i = 1;i < 64;i += 2) {
+ select(&t,i / 2,e[i]);
+ ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r);
+ }
+
+ ge_p3_dbl(&r,h); ge_p1p1_to_p2(&s,&r);
+ ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
+ ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r);
+ ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r);
+
+ for (i = 0;i < 64;i += 2) {
+ select(&t,i / 2,e[i]);
+ ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r);
+ }
+}
diff --git a/src/ext/ed25519/ref10/ge_sub.c b/src/ext/ed25519/ref10/ge_sub.c
new file mode 100644
index 0000000000..69f3d54062
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_sub.c
@@ -0,0 +1,11 @@
+#include "ge.h"
+
+/*
+r = p - q
+*/
+
+void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q)
+{
+ fe t0;
+#include "ge_sub.h"
+}
diff --git a/src/ext/ed25519/ref10/ge_sub.h b/src/ext/ed25519/ref10/ge_sub.h
new file mode 100644
index 0000000000..b4ef1f5dd0
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_sub.h
@@ -0,0 +1,97 @@
+
+/* qhasm: enter ge_sub */
+
+/* qhasm: fe X1 */
+
+/* qhasm: fe Y1 */
+
+/* qhasm: fe Z1 */
+
+/* qhasm: fe Z2 */
+
+/* qhasm: fe T1 */
+
+/* qhasm: fe ZZ */
+
+/* qhasm: fe YpX2 */
+
+/* qhasm: fe YmX2 */
+
+/* qhasm: fe T2d2 */
+
+/* qhasm: fe X3 */
+
+/* qhasm: fe Y3 */
+
+/* qhasm: fe Z3 */
+
+/* qhasm: fe T3 */
+
+/* qhasm: fe YpX1 */
+
+/* qhasm: fe YmX1 */
+
+/* qhasm: fe A */
+
+/* qhasm: fe B */
+
+/* qhasm: fe C */
+
+/* qhasm: fe D */
+
+/* qhasm: YpX1 = Y1+X1 */
+/* asm 1: fe_add(>YpX1=fe#1,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_add(>YpX1=r->X,<Y1=p->Y,<X1=p->X); */
+fe_add(r->X,p->Y,p->X);
+
+/* qhasm: YmX1 = Y1-X1 */
+/* asm 1: fe_sub(>YmX1=fe#2,<Y1=fe#12,<X1=fe#11); */
+/* asm 2: fe_sub(>YmX1=r->Y,<Y1=p->Y,<X1=p->X); */
+fe_sub(r->Y,p->Y,p->X);
+
+/* qhasm: A = YpX1*YmX2 */
+/* asm 1: fe_mul(>A=fe#3,<YpX1=fe#1,<YmX2=fe#16); */
+/* asm 2: fe_mul(>A=r->Z,<YpX1=r->X,<YmX2=q->YminusX); */
+fe_mul(r->Z,r->X,q->YminusX);
+
+/* qhasm: B = YmX1*YpX2 */
+/* asm 1: fe_mul(>B=fe#2,<YmX1=fe#2,<YpX2=fe#15); */
+/* asm 2: fe_mul(>B=r->Y,<YmX1=r->Y,<YpX2=q->YplusX); */
+fe_mul(r->Y,r->Y,q->YplusX);
+
+/* qhasm: C = T2d2*T1 */
+/* asm 1: fe_mul(>C=fe#4,<T2d2=fe#18,<T1=fe#14); */
+/* asm 2: fe_mul(>C=r->T,<T2d2=q->T2d,<T1=p->T); */
+fe_mul(r->T,q->T2d,p->T);
+
+/* qhasm: ZZ = Z1*Z2 */
+/* asm 1: fe_mul(>ZZ=fe#1,<Z1=fe#13,<Z2=fe#17); */
+/* asm 2: fe_mul(>ZZ=r->X,<Z1=p->Z,<Z2=q->Z); */
+fe_mul(r->X,p->Z,q->Z);
+
+/* qhasm: D = 2*ZZ */
+/* asm 1: fe_add(>D=fe#5,<ZZ=fe#1,<ZZ=fe#1); */
+/* asm 2: fe_add(>D=t0,<ZZ=r->X,<ZZ=r->X); */
+fe_add(t0,r->X,r->X);
+
+/* qhasm: X3 = A-B */
+/* asm 1: fe_sub(>X3=fe#1,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_sub(>X3=r->X,<A=r->Z,<B=r->Y); */
+fe_sub(r->X,r->Z,r->Y);
+
+/* qhasm: Y3 = A+B */
+/* asm 1: fe_add(>Y3=fe#2,<A=fe#3,<B=fe#2); */
+/* asm 2: fe_add(>Y3=r->Y,<A=r->Z,<B=r->Y); */
+fe_add(r->Y,r->Z,r->Y);
+
+/* qhasm: Z3 = D-C */
+/* asm 1: fe_sub(>Z3=fe#3,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_sub(>Z3=r->Z,<D=t0,<C=r->T); */
+fe_sub(r->Z,t0,r->T);
+
+/* qhasm: T3 = D+C */
+/* asm 1: fe_add(>T3=fe#4,<D=fe#5,<C=fe#4); */
+/* asm 2: fe_add(>T3=r->T,<D=t0,<C=r->T); */
+fe_add(r->T,t0,r->T);
+
+/* qhasm: return */
diff --git a/src/ext/ed25519/ref10/ge_sub.q b/src/ext/ed25519/ref10/ge_sub.q
new file mode 100644
index 0000000000..2779a4a201
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_sub.q
@@ -0,0 +1,49 @@
+:name:fe:r->X:r->Y:r->Z:r->T:t0:t1:t2:t3:t4:t5:p->X:p->Y:p->Z:p->T:q->YplusX:q->YminusX:q->Z:q->T2d:
+fe r:var/r=fe:
+
+enter f:enter/f:>X1=fe#11:>Y1=fe#12:>Z1=fe#13:>T1=fe#14:>YpX2=fe#15:>YmX2=fe#16:>Z2=fe#17:>T2d2=fe#18:
+return:nofallthrough:<X3=fe#1:<Y3=fe#2:<Z3=fe#3:<T3=fe#4:leave:
+
+h=f+g:<f=fe:<g=fe:>h=fe:asm/fe_add(>h,<f,<g);:
+h=f-g:<f=fe:<g=fe:>h=fe:asm/fe_sub(>h,<f,<g);:
+h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);:
+h=f^2:<f=fe:>h=fe:asm/fe_sq(>h,<f);:
+h=2*g:<g=fe:>h=fe:asm/fe_add(>h,<g,<g);:
+
+:
+
+enter ge_sub
+
+fe X1
+fe Y1
+fe Z1
+fe Z2
+fe T1
+fe ZZ
+fe YpX2
+fe YmX2
+fe T2d2
+fe X3
+fe Y3
+fe Z3
+fe T3
+fe YpX1
+fe YmX1
+fe A
+fe B
+fe C
+fe D
+
+YpX1 = Y1+X1
+YmX1 = Y1-X1
+A = YpX1*YmX2
+B = YmX1*YpX2
+C = T2d2*T1
+ZZ = Z1*Z2
+D = 2*ZZ
+X3 = A-B
+Y3 = A+B
+Z3 = D-C
+T3 = D+C
+
+return
diff --git a/src/ext/ed25519/ref10/ge_tobytes.c b/src/ext/ed25519/ref10/ge_tobytes.c
new file mode 100644
index 0000000000..31b3d33e09
--- /dev/null
+++ b/src/ext/ed25519/ref10/ge_tobytes.c
@@ -0,0 +1,14 @@
+#include "ge.h"
+
+void ge_tobytes(unsigned char *s,const ge_p2 *h)
+{
+ fe recip;
+ fe x;
+ fe y;
+
+ fe_invert(recip,h->Z);
+ fe_mul(x,h->X,recip);
+ fe_mul(y,h->Y,recip);
+ fe_tobytes(s,y);
+ s[31] ^= fe_isnegative(x) << 7;
+}
diff --git a/src/ext/ed25519/ref10/keyconv.c b/src/ext/ed25519/ref10/keyconv.c
new file mode 100644
index 0000000000..854b150d69
--- /dev/null
+++ b/src/ext/ed25519/ref10/keyconv.c
@@ -0,0 +1,37 @@
+/* Added to ref10 for Tor. We place this in the public domain. Alternatively,
+ * you may have it under the Creative Commons 0 "CC0" license. */
+#include "fe.h"
+#include "ed25519_ref10.h"
+
+int ed25519_ref10_pubkey_from_curve25519_pubkey(unsigned char *out,
+ const unsigned char *inp,
+ int signbit)
+{
+ fe u;
+ fe one;
+ fe y;
+ fe uplus1;
+ fe uminus1;
+ fe inv_uplus1;
+
+ /* From prop228:
+
+ Given a curve25519 x-coordinate (u), we can get the y coordinate
+ of the ed25519 key using
+
+ y = (u-1)/(u+1)
+ */
+ fe_frombytes(u, inp);
+ fe_1(one);
+ fe_sub(uminus1, u, one);
+ fe_add(uplus1, u, one);
+ fe_invert(inv_uplus1, uplus1);
+ fe_mul(y, uminus1, inv_uplus1);
+
+ fe_tobytes(out, y);
+
+ /* propagate sign. */
+ out[31] |= (!!signbit) << 7;
+
+ return 0;
+}
diff --git a/src/ext/ed25519/ref10/keypair.c b/src/ext/ed25519/ref10/keypair.c
new file mode 100644
index 0000000000..7ddbaa971e
--- /dev/null
+++ b/src/ext/ed25519/ref10/keypair.c
@@ -0,0 +1,51 @@
+/* Modified for Tor: new API, 64-byte secret keys. */
+#include <string.h>
+#include "randombytes.h"
+#include "crypto_sign.h"
+#include "crypto_hash_sha512.h"
+#include "ge.h"
+
+int
+crypto_sign_seckey(unsigned char *sk)
+{
+ unsigned char seed[32];
+
+ if (randombytes(seed,32) < 0)
+ return -1;
+
+ crypto_sign_seckey_expand(sk, seed);
+
+ memwipe(seed, 0, 32);
+
+ return 0;
+}
+
+int crypto_sign_seckey_expand(unsigned char *sk, const unsigned char *skseed)
+{
+ crypto_hash_sha512(sk,skseed,32);
+ sk[0] &= 248;
+ sk[31] &= 63;
+ sk[31] |= 64;
+
+ return 0;
+}
+
+int crypto_sign_pubkey(unsigned char *pk,const unsigned char *sk)
+{
+ ge_p3 A;
+
+ ge_scalarmult_base(&A,sk);
+ ge_p3_tobytes(pk,&A);
+
+ return 0;
+}
+
+
+int crypto_sign_keypair(unsigned char *pk,unsigned char *sk)
+{
+ crypto_sign_seckey(sk);
+ crypto_sign_pubkey(pk, sk);
+
+ return 0;
+}
+
diff --git a/src/ext/ed25519/ref10/open.c b/src/ext/ed25519/ref10/open.c
new file mode 100644
index 0000000000..9dbeb4cdd0
--- /dev/null
+++ b/src/ext/ed25519/ref10/open.c
@@ -0,0 +1,42 @@
+/* (Modified by Tor to verify signature separately from message) */
+#include <string.h>
+#include "crypto_sign.h"
+#include "crypto_hash_sha512.h"
+#include "crypto_verify_32.h"
+#include "ge.h"
+#include "sc.h"
+
+/* 'signature' must be 64-bytes long. */
+int crypto_sign_open(
+ const unsigned char *signature,
+ const unsigned char *m, size_t mlen,
+ const unsigned char *pk
+)
+{
+ unsigned char pkcopy[32];
+ unsigned char rcopy[32];
+ unsigned char scopy[32];
+ unsigned char h[64];
+ unsigned char rcheck[32];
+ ge_p3 A;
+ ge_p2 R;
+
+ if (signature[63] & 224) goto badsig;
+ if (ge_frombytes_negate_vartime(&A,pk) != 0) goto badsig;
+
+ memmove(pkcopy,pk,32);
+ memmove(rcopy,signature,32);
+ memmove(scopy,signature + 32,32);
+
+ crypto_hash_sha512_3(h, rcopy, 32, pkcopy, 32, m, mlen);
+ sc_reduce(h);
+
+ ge_double_scalarmult_vartime(&R,h,&A,scopy);
+ ge_tobytes(rcheck,&R);
+ if (crypto_verify_32(rcheck,rcopy) == 0) {
+ return 0;
+ }
+
+badsig:
+ return -1;
+}
diff --git a/src/ext/ed25519/ref10/pow22523.h b/src/ext/ed25519/ref10/pow22523.h
new file mode 100644
index 0000000000..9204ff838f
--- /dev/null
+++ b/src/ext/ed25519/ref10/pow22523.h
@@ -0,0 +1,161 @@
+/* Modified by Tor: pointless loops removed to appease analysis tools */
+
+/* qhasm: fe z1 */
+
+/* qhasm: fe z2 */
+
+/* qhasm: fe z8 */
+
+/* qhasm: fe z9 */
+
+/* qhasm: fe z11 */
+
+/* qhasm: fe z22 */
+
+/* qhasm: fe z_5_0 */
+
+/* qhasm: fe z_10_5 */
+
+/* qhasm: fe z_10_0 */
+
+/* qhasm: fe z_20_10 */
+
+/* qhasm: fe z_20_0 */
+
+/* qhasm: fe z_40_20 */
+
+/* qhasm: fe z_40_0 */
+
+/* qhasm: fe z_50_10 */
+
+/* qhasm: fe z_50_0 */
+
+/* qhasm: fe z_100_50 */
+
+/* qhasm: fe z_100_0 */
+
+/* qhasm: fe z_200_100 */
+
+/* qhasm: fe z_200_0 */
+
+/* qhasm: fe z_250_50 */
+
+/* qhasm: fe z_250_0 */
+
+/* qhasm: fe z_252_2 */
+
+/* qhasm: fe z_252_3 */
+
+/* qhasm: enter pow22523 */
+
+/* qhasm: z2 = z1^2^1 */
+/* asm 1: fe_sq(>z2=fe#1,<z1=fe#11); for (i = 1;i < 1;++i) fe_sq(>z2=fe#1,>z2=fe#1); */
+/* asm 2: fe_sq(>z2=t0,<z1=z); for (i = 1;i < 1;++i) fe_sq(>z2=t0,>z2=t0); */
+fe_sq(t0,z); /* DEADCODE This loop has no effect: for (i = 1;i < 1;++i) fe_sq(t0,t0); */
+
+/* qhasm: z8 = z2^2^2 */
+/* asm 1: fe_sq(>z8=fe#2,<z2=fe#1); for (i = 1;i < 2;++i) fe_sq(>z8=fe#2,>z8=fe#2); */
+/* asm 2: fe_sq(>z8=t1,<z2=t0); for (i = 1;i < 2;++i) fe_sq(>z8=t1,>z8=t1); */
+fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1);
+
+/* qhasm: z9 = z1*z8 */
+/* asm 1: fe_mul(>z9=fe#2,<z1=fe#11,<z8=fe#2); */
+/* asm 2: fe_mul(>z9=t1,<z1=z,<z8=t1); */
+fe_mul(t1,z,t1);
+
+/* qhasm: z11 = z2*z9 */
+/* asm 1: fe_mul(>z11=fe#1,<z2=fe#1,<z9=fe#2); */
+/* asm 2: fe_mul(>z11=t0,<z2=t0,<z9=t1); */
+fe_mul(t0,t0,t1);
+
+/* qhasm: z22 = z11^2^1 */
+/* asm 1: fe_sq(>z22=fe#1,<z11=fe#1); for (i = 1;i < 1;++i) fe_sq(>z22=fe#1,>z22=fe#1); */
+/* asm 2: fe_sq(>z22=t0,<z11=t0); for (i = 1;i < 1;++i) fe_sq(>z22=t0,>z22=t0); */
+fe_sq(t0,t0); /* DEADCODE This loop has no effect: for (i = 1;i < 1;++i) fe_sq(t0,t0); */
+
+/* qhasm: z_5_0 = z9*z22 */
+/* asm 1: fe_mul(>z_5_0=fe#1,<z9=fe#2,<z22=fe#1); */
+/* asm 2: fe_mul(>z_5_0=t0,<z9=t1,<z22=t0); */
+fe_mul(t0,t1,t0);
+
+/* qhasm: z_10_5 = z_5_0^2^5 */
+/* asm 1: fe_sq(>z_10_5=fe#2,<z_5_0=fe#1); for (i = 1;i < 5;++i) fe_sq(>z_10_5=fe#2,>z_10_5=fe#2); */
+/* asm 2: fe_sq(>z_10_5=t1,<z_5_0=t0); for (i = 1;i < 5;++i) fe_sq(>z_10_5=t1,>z_10_5=t1); */
+fe_sq(t1,t0); for (i = 1;i < 5;++i) fe_sq(t1,t1);
+
+/* qhasm: z_10_0 = z_10_5*z_5_0 */
+/* asm 1: fe_mul(>z_10_0=fe#1,<z_10_5=fe#2,<z_5_0=fe#1); */
+/* asm 2: fe_mul(>z_10_0=t0,<z_10_5=t1,<z_5_0=t0); */
+fe_mul(t0,t1,t0);
+
+/* qhasm: z_20_10 = z_10_0^2^10 */
+/* asm 1: fe_sq(>z_20_10=fe#2,<z_10_0=fe#1); for (i = 1;i < 10;++i) fe_sq(>z_20_10=fe#2,>z_20_10=fe#2); */
+/* asm 2: fe_sq(>z_20_10=t1,<z_10_0=t0); for (i = 1;i < 10;++i) fe_sq(>z_20_10=t1,>z_20_10=t1); */
+fe_sq(t1,t0); for (i = 1;i < 10;++i) fe_sq(t1,t1);
+
+/* qhasm: z_20_0 = z_20_10*z_10_0 */
+/* asm 1: fe_mul(>z_20_0=fe#2,<z_20_10=fe#2,<z_10_0=fe#1); */
+/* asm 2: fe_mul(>z_20_0=t1,<z_20_10=t1,<z_10_0=t0); */
+fe_mul(t1,t1,t0);
+
+/* qhasm: z_40_20 = z_20_0^2^20 */
+/* asm 1: fe_sq(>z_40_20=fe#3,<z_20_0=fe#2); for (i = 1;i < 20;++i) fe_sq(>z_40_20=fe#3,>z_40_20=fe#3); */
+/* asm 2: fe_sq(>z_40_20=t2,<z_20_0=t1); for (i = 1;i < 20;++i) fe_sq(>z_40_20=t2,>z_40_20=t2); */
+fe_sq(t2,t1); for (i = 1;i < 20;++i) fe_sq(t2,t2);
+
+/* qhasm: z_40_0 = z_40_20*z_20_0 */
+/* asm 1: fe_mul(>z_40_0=fe#2,<z_40_20=fe#3,<z_20_0=fe#2); */
+/* asm 2: fe_mul(>z_40_0=t1,<z_40_20=t2,<z_20_0=t1); */
+fe_mul(t1,t2,t1);
+
+/* qhasm: z_50_10 = z_40_0^2^10 */
+/* asm 1: fe_sq(>z_50_10=fe#2,<z_40_0=fe#2); for (i = 1;i < 10;++i) fe_sq(>z_50_10=fe#2,>z_50_10=fe#2); */
+/* asm 2: fe_sq(>z_50_10=t1,<z_40_0=t1); for (i = 1;i < 10;++i) fe_sq(>z_50_10=t1,>z_50_10=t1); */
+fe_sq(t1,t1); for (i = 1;i < 10;++i) fe_sq(t1,t1);
+
+/* qhasm: z_50_0 = z_50_10*z_10_0 */
+/* asm 1: fe_mul(>z_50_0=fe#1,<z_50_10=fe#2,<z_10_0=fe#1); */
+/* asm 2: fe_mul(>z_50_0=t0,<z_50_10=t1,<z_10_0=t0); */
+fe_mul(t0,t1,t0);
+
+/* qhasm: z_100_50 = z_50_0^2^50 */
+/* asm 1: fe_sq(>z_100_50=fe#2,<z_50_0=fe#1); for (i = 1;i < 50;++i) fe_sq(>z_100_50=fe#2,>z_100_50=fe#2); */
+/* asm 2: fe_sq(>z_100_50=t1,<z_50_0=t0); for (i = 1;i < 50;++i) fe_sq(>z_100_50=t1,>z_100_50=t1); */
+fe_sq(t1,t0); for (i = 1;i < 50;++i) fe_sq(t1,t1);
+
+/* qhasm: z_100_0 = z_100_50*z_50_0 */
+/* asm 1: fe_mul(>z_100_0=fe#2,<z_100_50=fe#2,<z_50_0=fe#1); */
+/* asm 2: fe_mul(>z_100_0=t1,<z_100_50=t1,<z_50_0=t0); */
+fe_mul(t1,t1,t0);
+
+/* qhasm: z_200_100 = z_100_0^2^100 */
+/* asm 1: fe_sq(>z_200_100=fe#3,<z_100_0=fe#2); for (i = 1;i < 100;++i) fe_sq(>z_200_100=fe#3,>z_200_100=fe#3); */
+/* asm 2: fe_sq(>z_200_100=t2,<z_100_0=t1); for (i = 1;i < 100;++i) fe_sq(>z_200_100=t2,>z_200_100=t2); */
+fe_sq(t2,t1); for (i = 1;i < 100;++i) fe_sq(t2,t2);
+
+/* qhasm: z_200_0 = z_200_100*z_100_0 */
+/* asm 1: fe_mul(>z_200_0=fe#2,<z_200_100=fe#3,<z_100_0=fe#2); */
+/* asm 2: fe_mul(>z_200_0=t1,<z_200_100=t2,<z_100_0=t1); */
+fe_mul(t1,t2,t1);
+
+/* qhasm: z_250_50 = z_200_0^2^50 */
+/* asm 1: fe_sq(>z_250_50=fe#2,<z_200_0=fe#2); for (i = 1;i < 50;++i) fe_sq(>z_250_50=fe#2,>z_250_50=fe#2); */
+/* asm 2: fe_sq(>z_250_50=t1,<z_200_0=t1); for (i = 1;i < 50;++i) fe_sq(>z_250_50=t1,>z_250_50=t1); */
+fe_sq(t1,t1); for (i = 1;i < 50;++i) fe_sq(t1,t1);
+
+/* qhasm: z_250_0 = z_250_50*z_50_0 */
+/* asm 1: fe_mul(>z_250_0=fe#1,<z_250_50=fe#2,<z_50_0=fe#1); */
+/* asm 2: fe_mul(>z_250_0=t0,<z_250_50=t1,<z_50_0=t0); */
+fe_mul(t0,t1,t0);
+
+/* qhasm: z_252_2 = z_250_0^2^2 */
+/* asm 1: fe_sq(>z_252_2=fe#1,<z_250_0=fe#1); for (i = 1;i < 2;++i) fe_sq(>z_252_2=fe#1,>z_252_2=fe#1); */
+/* asm 2: fe_sq(>z_252_2=t0,<z_250_0=t0); for (i = 1;i < 2;++i) fe_sq(>z_252_2=t0,>z_252_2=t0); */
+fe_sq(t0,t0); for (i = 1;i < 2;++i) fe_sq(t0,t0);
+
+/* qhasm: z_252_3 = z_252_2*z1 */
+/* asm 1: fe_mul(>z_252_3=fe#12,<z_252_2=fe#1,<z1=fe#11); */
+/* asm 2: fe_mul(>z_252_3=out,<z_252_2=t0,<z1=z); */
+fe_mul(out,t0,z);
+
+/* qhasm: return */
diff --git a/src/ext/ed25519/ref10/pow22523.q b/src/ext/ed25519/ref10/pow22523.q
new file mode 100644
index 0000000000..2ce1da9d4d
--- /dev/null
+++ b/src/ext/ed25519/ref10/pow22523.q
@@ -0,0 +1,61 @@
+:name:fe:t0:t1:t2:t3:t4:t5:t6:t7:t8:t9:z:out:
+fe r:var/r=fe:
+
+enter f:enter/f:>z1=fe#11:
+return:nofallthrough:<z_252_3=fe#12:leave:
+
+h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);:
+h=f^2^k:<f=fe:>h=fe:#k:asm/fe_sq(>h,<f); for (i = 1;i !lt; #k;++i) fe_sq(>h,>h);:
+
+:
+
+fe z1
+fe z2
+fe z8
+fe z9
+fe z11
+fe z22
+fe z_5_0
+fe z_10_5
+fe z_10_0
+fe z_20_10
+fe z_20_0
+fe z_40_20
+fe z_40_0
+fe z_50_10
+fe z_50_0
+fe z_100_50
+fe z_100_0
+fe z_200_100
+fe z_200_0
+fe z_250_50
+fe z_250_0
+fe z_252_2
+fe z_252_3
+
+enter pow22523
+
+z2 = z1^2^1
+z8 = z2^2^2
+z9 = z1*z8
+z11 = z2*z9
+z22 = z11^2^1
+z_5_0 = z9*z22
+z_10_5 = z_5_0^2^5
+z_10_0 = z_10_5*z_5_0
+z_20_10 = z_10_0^2^10
+z_20_0 = z_20_10*z_10_0
+z_40_20 = z_20_0^2^20
+z_40_0 = z_40_20*z_20_0
+z_50_10 = z_40_0^2^10
+z_50_0 = z_50_10*z_10_0
+z_100_50 = z_50_0^2^50
+z_100_0 = z_100_50*z_50_0
+z_200_100 = z_100_0^2^100
+z_200_0 = z_200_100*z_100_0
+z_250_50 = z_200_0^2^50
+z_250_0 = z_250_50*z_50_0
+z_252_2 = z_250_0^2^2
+z_252_3 = z_252_2*z1
+
+return
diff --git a/src/ext/ed25519/ref10/pow225521.h b/src/ext/ed25519/ref10/pow225521.h
new file mode 100644
index 0000000000..fe2af94c03
--- /dev/null
+++ b/src/ext/ed25519/ref10/pow225521.h
@@ -0,0 +1,161 @@
+/* Modified by Tor: pointless loops removed to appease analysis tools */
+
+/* qhasm: fe z1 */
+
+/* qhasm: fe z2 */
+
+/* qhasm: fe z8 */
+
+/* qhasm: fe z9 */
+
+/* qhasm: fe z11 */
+
+/* qhasm: fe z22 */
+
+/* qhasm: fe z_5_0 */
+
+/* qhasm: fe z_10_5 */
+
+/* qhasm: fe z_10_0 */
+
+/* qhasm: fe z_20_10 */
+
+/* qhasm: fe z_20_0 */
+
+/* qhasm: fe z_40_20 */
+
+/* qhasm: fe z_40_0 */
+
+/* qhasm: fe z_50_10 */
+
+/* qhasm: fe z_50_0 */
+
+/* qhasm: fe z_100_50 */
+
+/* qhasm: fe z_100_0 */
+
+/* qhasm: fe z_200_100 */
+
+/* qhasm: fe z_200_0 */
+
+/* qhasm: fe z_250_50 */
+
+/* qhasm: fe z_250_0 */
+
+/* qhasm: fe z_255_5 */
+
+/* qhasm: fe z_255_21 */
+
+/* qhasm: enter pow225521 */
+
+/* qhasm: z2 = z1^2^1 */
+/* asm 1: fe_sq(>z2=fe#1,<z1=fe#11); for (i = 1;i < 1;++i) fe_sq(>z2=fe#1,>z2=fe#1); */
+/* asm 2: fe_sq(>z2=t0,<z1=z); for (i = 1;i < 1;++i) fe_sq(>z2=t0,>z2=t0); */
+fe_sq(t0,z); /* DEADCODE This loop has no effect: for (i = 1;i < 1;++i) fe_sq(t0,t0); */
+
+/* qhasm: z8 = z2^2^2 */
+/* asm 1: fe_sq(>z8=fe#2,<z2=fe#1); for (i = 1;i < 2;++i) fe_sq(>z8=fe#2,>z8=fe#2); */
+/* asm 2: fe_sq(>z8=t1,<z2=t0); for (i = 1;i < 2;++i) fe_sq(>z8=t1,>z8=t1); */
+fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1);
+
+/* qhasm: z9 = z1*z8 */
+/* asm 1: fe_mul(>z9=fe#2,<z1=fe#11,<z8=fe#2); */
+/* asm 2: fe_mul(>z9=t1,<z1=z,<z8=t1); */
+fe_mul(t1,z,t1);
+
+/* qhasm: z11 = z2*z9 */
+/* asm 1: fe_mul(>z11=fe#1,<z2=fe#1,<z9=fe#2); */
+/* asm 2: fe_mul(>z11=t0,<z2=t0,<z9=t1); */
+fe_mul(t0,t0,t1);
+
+/* qhasm: z22 = z11^2^1 */
+/* asm 1: fe_sq(>z22=fe#3,<z11=fe#1); for (i = 1;i < 1;++i) fe_sq(>z22=fe#3,>z22=fe#3); */
+/* asm 2: fe_sq(>z22=t2,<z11=t0); for (i = 1;i < 1;++i) fe_sq(>z22=t2,>z22=t2); */
+fe_sq(t2,t0); /* DEADCODE This loop has no effect for (i = 1;i < 1;++i) fe_sq(t2,t2); */
+
+/* qhasm: z_5_0 = z9*z22 */
+/* asm 1: fe_mul(>z_5_0=fe#2,<z9=fe#2,<z22=fe#3); */
+/* asm 2: fe_mul(>z_5_0=t1,<z9=t1,<z22=t2); */
+fe_mul(t1,t1,t2);
+
+/* qhasm: z_10_5 = z_5_0^2^5 */
+/* asm 1: fe_sq(>z_10_5=fe#3,<z_5_0=fe#2); for (i = 1;i < 5;++i) fe_sq(>z_10_5=fe#3,>z_10_5=fe#3); */
+/* asm 2: fe_sq(>z_10_5=t2,<z_5_0=t1); for (i = 1;i < 5;++i) fe_sq(>z_10_5=t2,>z_10_5=t2); */
+fe_sq(t2,t1); for (i = 1;i < 5;++i) fe_sq(t2,t2);
+
+/* qhasm: z_10_0 = z_10_5*z_5_0 */
+/* asm 1: fe_mul(>z_10_0=fe#2,<z_10_5=fe#3,<z_5_0=fe#2); */
+/* asm 2: fe_mul(>z_10_0=t1,<z_10_5=t2,<z_5_0=t1); */
+fe_mul(t1,t2,t1);
+
+/* qhasm: z_20_10 = z_10_0^2^10 */
+/* asm 1: fe_sq(>z_20_10=fe#3,<z_10_0=fe#2); for (i = 1;i < 10;++i) fe_sq(>z_20_10=fe#3,>z_20_10=fe#3); */
+/* asm 2: fe_sq(>z_20_10=t2,<z_10_0=t1); for (i = 1;i < 10;++i) fe_sq(>z_20_10=t2,>z_20_10=t2); */
+fe_sq(t2,t1); for (i = 1;i < 10;++i) fe_sq(t2,t2);
+
+/* qhasm: z_20_0 = z_20_10*z_10_0 */
+/* asm 1: fe_mul(>z_20_0=fe#3,<z_20_10=fe#3,<z_10_0=fe#2); */
+/* asm 2: fe_mul(>z_20_0=t2,<z_20_10=t2,<z_10_0=t1); */
+fe_mul(t2,t2,t1);
+
+/* qhasm: z_40_20 = z_20_0^2^20 */
+/* asm 1: fe_sq(>z_40_20=fe#4,<z_20_0=fe#3); for (i = 1;i < 20;++i) fe_sq(>z_40_20=fe#4,>z_40_20=fe#4); */
+/* asm 2: fe_sq(>z_40_20=t3,<z_20_0=t2); for (i = 1;i < 20;++i) fe_sq(>z_40_20=t3,>z_40_20=t3); */
+fe_sq(t3,t2); for (i = 1;i < 20;++i) fe_sq(t3,t3);
+
+/* qhasm: z_40_0 = z_40_20*z_20_0 */
+/* asm 1: fe_mul(>z_40_0=fe#3,<z_40_20=fe#4,<z_20_0=fe#3); */
+/* asm 2: fe_mul(>z_40_0=t2,<z_40_20=t3,<z_20_0=t2); */
+fe_mul(t2,t3,t2);
+
+/* qhasm: z_50_10 = z_40_0^2^10 */
+/* asm 1: fe_sq(>z_50_10=fe#3,<z_40_0=fe#3); for (i = 1;i < 10;++i) fe_sq(>z_50_10=fe#3,>z_50_10=fe#3); */
+/* asm 2: fe_sq(>z_50_10=t2,<z_40_0=t2); for (i = 1;i < 10;++i) fe_sq(>z_50_10=t2,>z_50_10=t2); */
+fe_sq(t2,t2); for (i = 1;i < 10;++i) fe_sq(t2,t2);
+
+/* qhasm: z_50_0 = z_50_10*z_10_0 */
+/* asm 1: fe_mul(>z_50_0=fe#2,<z_50_10=fe#3,<z_10_0=fe#2); */
+/* asm 2: fe_mul(>z_50_0=t1,<z_50_10=t2,<z_10_0=t1); */
+fe_mul(t1,t2,t1);
+
+/* qhasm: z_100_50 = z_50_0^2^50 */
+/* asm 1: fe_sq(>z_100_50=fe#3,<z_50_0=fe#2); for (i = 1;i < 50;++i) fe_sq(>z_100_50=fe#3,>z_100_50=fe#3); */
+/* asm 2: fe_sq(>z_100_50=t2,<z_50_0=t1); for (i = 1;i < 50;++i) fe_sq(>z_100_50=t2,>z_100_50=t2); */
+fe_sq(t2,t1); for (i = 1;i < 50;++i) fe_sq(t2,t2);
+
+/* qhasm: z_100_0 = z_100_50*z_50_0 */
+/* asm 1: fe_mul(>z_100_0=fe#3,<z_100_50=fe#3,<z_50_0=fe#2); */
+/* asm 2: fe_mul(>z_100_0=t2,<z_100_50=t2,<z_50_0=t1); */
+fe_mul(t2,t2,t1);
+
+/* qhasm: z_200_100 = z_100_0^2^100 */
+/* asm 1: fe_sq(>z_200_100=fe#4,<z_100_0=fe#3); for (i = 1;i < 100;++i) fe_sq(>z_200_100=fe#4,>z_200_100=fe#4); */
+/* asm 2: fe_sq(>z_200_100=t3,<z_100_0=t2); for (i = 1;i < 100;++i) fe_sq(>z_200_100=t3,>z_200_100=t3); */
+fe_sq(t3,t2); for (i = 1;i < 100;++i) fe_sq(t3,t3);
+
+/* qhasm: z_200_0 = z_200_100*z_100_0 */
+/* asm 1: fe_mul(>z_200_0=fe#3,<z_200_100=fe#4,<z_100_0=fe#3); */
+/* asm 2: fe_mul(>z_200_0=t2,<z_200_100=t3,<z_100_0=t2); */
+fe_mul(t2,t3,t2);
+
+/* qhasm: z_250_50 = z_200_0^2^50 */
+/* asm 1: fe_sq(>z_250_50=fe#3,<z_200_0=fe#3); for (i = 1;i < 50;++i) fe_sq(>z_250_50=fe#3,>z_250_50=fe#3); */
+/* asm 2: fe_sq(>z_250_50=t2,<z_200_0=t2); for (i = 1;i < 50;++i) fe_sq(>z_250_50=t2,>z_250_50=t2); */
+fe_sq(t2,t2); for (i = 1;i < 50;++i) fe_sq(t2,t2);
+
+/* qhasm: z_250_0 = z_250_50*z_50_0 */
+/* asm 1: fe_mul(>z_250_0=fe#2,<z_250_50=fe#3,<z_50_0=fe#2); */
+/* asm 2: fe_mul(>z_250_0=t1,<z_250_50=t2,<z_50_0=t1); */
+fe_mul(t1,t2,t1);
+
+/* qhasm: z_255_5 = z_250_0^2^5 */
+/* asm 1: fe_sq(>z_255_5=fe#2,<z_250_0=fe#2); for (i = 1;i < 5;++i) fe_sq(>z_255_5=fe#2,>z_255_5=fe#2); */
+/* asm 2: fe_sq(>z_255_5=t1,<z_250_0=t1); for (i = 1;i < 5;++i) fe_sq(>z_255_5=t1,>z_255_5=t1); */
+fe_sq(t1,t1); for (i = 1;i < 5;++i) fe_sq(t1,t1);
+
+/* qhasm: z_255_21 = z_255_5*z11 */
+/* asm 1: fe_mul(>z_255_21=fe#12,<z_255_5=fe#2,<z11=fe#1); */
+/* asm 2: fe_mul(>z_255_21=out,<z_255_5=t1,<z11=t0); */
+fe_mul(out,t1,t0);
+
+/* qhasm: return */
diff --git a/src/ext/ed25519/ref10/pow225521.q b/src/ext/ed25519/ref10/pow225521.q
new file mode 100644
index 0000000000..45be57c08a
--- /dev/null
+++ b/src/ext/ed25519/ref10/pow225521.q
@@ -0,0 +1,61 @@
+:name:fe:t0:t1:t2:t3:t4:t5:t6:t7:t8:t9:z:out:
+fe r:var/r=fe:
+
+enter f:enter/f:>z1=fe#11:
+return:nofallthrough:<z_255_21=fe#12:leave:
+
+h=f*g:<f=fe:<g=fe:>h=fe:asm/fe_mul(>h,<f,<g);:
+h=f^2^k:<f=fe:>h=fe:#k:asm/fe_sq(>h,<f); for (i = 1;i !lt; #k;++i) fe_sq(>h,>h);:
+
+:
+
+fe z1
+fe z2
+fe z8
+fe z9
+fe z11
+fe z22
+fe z_5_0
+fe z_10_5
+fe z_10_0
+fe z_20_10
+fe z_20_0
+fe z_40_20
+fe z_40_0
+fe z_50_10
+fe z_50_0
+fe z_100_50
+fe z_100_0
+fe z_200_100
+fe z_200_0
+fe z_250_50
+fe z_250_0
+fe z_255_5
+fe z_255_21
+
+enter pow225521
+
+z2 = z1^2^1
+z8 = z2^2^2
+z9 = z1*z8
+z11 = z2*z9
+z22 = z11^2^1
+z_5_0 = z9*z22
+z_10_5 = z_5_0^2^5
+z_10_0 = z_10_5*z_5_0
+z_20_10 = z_10_0^2^10
+z_20_0 = z_20_10*z_10_0
+z_40_20 = z_20_0^2^20
+z_40_0 = z_40_20*z_20_0
+z_50_10 = z_40_0^2^10
+z_50_0 = z_50_10*z_10_0
+z_100_50 = z_50_0^2^50
+z_100_0 = z_100_50*z_50_0
+z_200_100 = z_100_0^2^100
+z_200_0 = z_200_100*z_100_0
+z_250_50 = z_200_0^2^50
+z_250_0 = z_250_50*z_50_0
+z_255_5 = z_250_0^2^5
+z_255_21 = z_255_5*z11
+
+return
diff --git a/src/ext/ed25519/ref10/q2h.sh b/src/ext/ed25519/ref10/q2h.sh
new file mode 100755
index 0000000000..47ec5110e8
--- /dev/null
+++ b/src/ext/ed25519/ref10/q2h.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+sed 's/^#.*//' \
+| qhasm-generic \
+| sed 's_//\(.*\)$_/*\1 */_'
diff --git a/src/ext/ed25519/ref10/randombytes.h b/src/ext/ed25519/ref10/randombytes.h
new file mode 100644
index 0000000000..fc709fcefc
--- /dev/null
+++ b/src/ext/ed25519/ref10/randombytes.h
@@ -0,0 +1,4 @@
+/* Added for Tor. */
+#include "crypto.h"
+#define randombytes(b, n) \
+ (crypto_strongest_rand((b), (n)))
diff --git a/src/ext/ed25519/ref10/sc.h b/src/ext/ed25519/ref10/sc.h
new file mode 100644
index 0000000000..d32ed2e8ca
--- /dev/null
+++ b/src/ext/ed25519/ref10/sc.h
@@ -0,0 +1,15 @@
+#ifndef SC_H
+#define SC_H
+
+/*
+The set of scalars is \Z/l
+where l = 2^252 + 27742317777372353535851937790883648493.
+*/
+
+#define sc_reduce crypto_sign_ed25519_ref10_sc_reduce
+#define sc_muladd crypto_sign_ed25519_ref10_sc_muladd
+
+extern void sc_reduce(unsigned char *);
+extern void sc_muladd(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *);
+
+#endif
diff --git a/src/ext/ed25519/ref10/sc_muladd.c b/src/ext/ed25519/ref10/sc_muladd.c
new file mode 100644
index 0000000000..20b94c1049
--- /dev/null
+++ b/src/ext/ed25519/ref10/sc_muladd.c
@@ -0,0 +1,368 @@
+#include "sc.h"
+#include "crypto_int64.h"
+#include "crypto_uint32.h"
+#include "crypto_uint64.h"
+
+static crypto_uint64 load_3(const unsigned char *in)
+{
+ crypto_uint64 result;
+ result = (crypto_uint64) in[0];
+ result |= ((crypto_uint64) in[1]) << 8;
+ result |= ((crypto_uint64) in[2]) << 16;
+ return result;
+}
+
+static crypto_uint64 load_4(const unsigned char *in)
+{
+ crypto_uint64 result;
+ result = (crypto_uint64) in[0];
+ result |= ((crypto_uint64) in[1]) << 8;
+ result |= ((crypto_uint64) in[2]) << 16;
+ result |= ((crypto_uint64) in[3]) << 24;
+ return result;
+}
+
+/*
+Input:
+ a[0]+256*a[1]+...+256^31*a[31] = a
+ b[0]+256*b[1]+...+256^31*b[31] = b
+ c[0]+256*c[1]+...+256^31*c[31] = c
+
+Output:
+ s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
+ where l = 2^252 + 27742317777372353535851937790883648493.
+*/
+
+void sc_muladd(unsigned char *s,const unsigned char *a,const unsigned char *b,const unsigned char *c)
+{
+ crypto_int64 a0 = 2097151 & load_3(a);
+ crypto_int64 a1 = 2097151 & (load_4(a + 2) >> 5);
+ crypto_int64 a2 = 2097151 & (load_3(a + 5) >> 2);
+ crypto_int64 a3 = 2097151 & (load_4(a + 7) >> 7);
+ crypto_int64 a4 = 2097151 & (load_4(a + 10) >> 4);
+ crypto_int64 a5 = 2097151 & (load_3(a + 13) >> 1);
+ crypto_int64 a6 = 2097151 & (load_4(a + 15) >> 6);
+ crypto_int64 a7 = 2097151 & (load_3(a + 18) >> 3);
+ crypto_int64 a8 = 2097151 & load_3(a + 21);
+ crypto_int64 a9 = 2097151 & (load_4(a + 23) >> 5);
+ crypto_int64 a10 = 2097151 & (load_3(a + 26) >> 2);
+ crypto_int64 a11 = (load_4(a + 28) >> 7);
+ crypto_int64 b0 = 2097151 & load_3(b);
+ crypto_int64 b1 = 2097151 & (load_4(b + 2) >> 5);
+ crypto_int64 b2 = 2097151 & (load_3(b + 5) >> 2);
+ crypto_int64 b3 = 2097151 & (load_4(b + 7) >> 7);
+ crypto_int64 b4 = 2097151 & (load_4(b + 10) >> 4);
+ crypto_int64 b5 = 2097151 & (load_3(b + 13) >> 1);
+ crypto_int64 b6 = 2097151 & (load_4(b + 15) >> 6);
+ crypto_int64 b7 = 2097151 & (load_3(b + 18) >> 3);
+ crypto_int64 b8 = 2097151 & load_3(b + 21);
+ crypto_int64 b9 = 2097151 & (load_4(b + 23) >> 5);
+ crypto_int64 b10 = 2097151 & (load_3(b + 26) >> 2);
+ crypto_int64 b11 = (load_4(b + 28) >> 7);
+ crypto_int64 c0 = 2097151 & load_3(c);
+ crypto_int64 c1 = 2097151 & (load_4(c + 2) >> 5);
+ crypto_int64 c2 = 2097151 & (load_3(c + 5) >> 2);
+ crypto_int64 c3 = 2097151 & (load_4(c + 7) >> 7);
+ crypto_int64 c4 = 2097151 & (load_4(c + 10) >> 4);
+ crypto_int64 c5 = 2097151 & (load_3(c + 13) >> 1);
+ crypto_int64 c6 = 2097151 & (load_4(c + 15) >> 6);
+ crypto_int64 c7 = 2097151 & (load_3(c + 18) >> 3);
+ crypto_int64 c8 = 2097151 & load_3(c + 21);
+ crypto_int64 c9 = 2097151 & (load_4(c + 23) >> 5);
+ crypto_int64 c10 = 2097151 & (load_3(c + 26) >> 2);
+ crypto_int64 c11 = (load_4(c + 28) >> 7);
+ crypto_int64 s0;
+ crypto_int64 s1;
+ crypto_int64 s2;
+ crypto_int64 s3;
+ crypto_int64 s4;
+ crypto_int64 s5;
+ crypto_int64 s6;
+ crypto_int64 s7;
+ crypto_int64 s8;
+ crypto_int64 s9;
+ crypto_int64 s10;
+ crypto_int64 s11;
+ crypto_int64 s12;
+ crypto_int64 s13;
+ crypto_int64 s14;
+ crypto_int64 s15;
+ crypto_int64 s16;
+ crypto_int64 s17;
+ crypto_int64 s18;
+ crypto_int64 s19;
+ crypto_int64 s20;
+ crypto_int64 s21;
+ crypto_int64 s22;
+ crypto_int64 s23;
+ crypto_int64 carry0;
+ crypto_int64 carry1;
+ crypto_int64 carry2;
+ crypto_int64 carry3;
+ crypto_int64 carry4;
+ crypto_int64 carry5;
+ crypto_int64 carry6;
+ crypto_int64 carry7;
+ crypto_int64 carry8;
+ crypto_int64 carry9;
+ crypto_int64 carry10;
+ crypto_int64 carry11;
+ crypto_int64 carry12;
+ crypto_int64 carry13;
+ crypto_int64 carry14;
+ crypto_int64 carry15;
+ crypto_int64 carry16;
+ crypto_int64 carry17;
+ crypto_int64 carry18;
+ crypto_int64 carry19;
+ crypto_int64 carry20;
+ crypto_int64 carry21;
+ crypto_int64 carry22;
+
+ s0 = c0 + a0*b0;
+ s1 = c1 + a0*b1 + a1*b0;
+ s2 = c2 + a0*b2 + a1*b1 + a2*b0;
+ s3 = c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0;
+ s4 = c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0;
+ s5 = c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0;
+ s6 = c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0;
+ s7 = c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0;
+ s8 = c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0;
+ s9 = c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0;
+ s10 = c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0;
+ s11 = c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0;
+ s12 = a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1;
+ s13 = a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2;
+ s14 = a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3;
+ s15 = a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4;
+ s16 = a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5;
+ s17 = a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6;
+ s18 = a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7;
+ s19 = a8*b11 + a9*b10 + a10*b9 + a11*b8;
+ s20 = a9*b11 + a10*b10 + a11*b9;
+ s21 = a10*b11 + a11*b10;
+ s22 = a11*b11;
+ s23 = 0;
+
+ carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= SHL64(carry0,21);
+ carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= SHL64(carry2,21);
+ carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= SHL64(carry4,21);
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21);
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21);
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21);
+ carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= SHL64(carry12,21);
+ carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= SHL64(carry14,21);
+ carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= SHL64(carry16,21);
+ carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= SHL64(carry18,21);
+ carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= SHL64(carry20,21);
+ carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= SHL64(carry22,21);
+
+ carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= SHL64(carry1,21);
+ carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= SHL64(carry3,21);
+ carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= SHL64(carry5,21);
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21);
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21);
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21);
+ carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= SHL64(carry13,21);
+ carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= SHL64(carry15,21);
+ carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= SHL64(carry17,21);
+ carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= SHL64(carry19,21);
+ carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= SHL64(carry21,21);
+
+ s11 += s23 * 666643;
+ s12 += s23 * 470296;
+ s13 += s23 * 654183;
+ s14 -= s23 * 997805;
+ s15 += s23 * 136657;
+ s16 -= s23 * 683901;
+ s23 = 0;
+
+ s10 += s22 * 666643;
+ s11 += s22 * 470296;
+ s12 += s22 * 654183;
+ s13 -= s22 * 997805;
+ s14 += s22 * 136657;
+ s15 -= s22 * 683901;
+ s22 = 0;
+
+ s9 += s21 * 666643;
+ s10 += s21 * 470296;
+ s11 += s21 * 654183;
+ s12 -= s21 * 997805;
+ s13 += s21 * 136657;
+ s14 -= s21 * 683901;
+ s21 = 0;
+
+ s8 += s20 * 666643;
+ s9 += s20 * 470296;
+ s10 += s20 * 654183;
+ s11 -= s20 * 997805;
+ s12 += s20 * 136657;
+ s13 -= s20 * 683901;
+ s20 = 0;
+
+ s7 += s19 * 666643;
+ s8 += s19 * 470296;
+ s9 += s19 * 654183;
+ s10 -= s19 * 997805;
+ s11 += s19 * 136657;
+ s12 -= s19 * 683901;
+ s19 = 0;
+
+ s6 += s18 * 666643;
+ s7 += s18 * 470296;
+ s8 += s18 * 654183;
+ s9 -= s18 * 997805;
+ s10 += s18 * 136657;
+ s11 -= s18 * 683901;
+ s18 = 0;
+
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21);
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21);
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21);
+ carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= SHL64(carry12,21);
+ carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= SHL64(carry14,21);
+ carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= SHL64(carry16,21);
+
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21);
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21);
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21);
+ carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= SHL64(carry13,21);
+ carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= SHL64(carry15,21);
+
+ s5 += s17 * 666643;
+ s6 += s17 * 470296;
+ s7 += s17 * 654183;
+ s8 -= s17 * 997805;
+ s9 += s17 * 136657;
+ s10 -= s17 * 683901;
+ s17 = 0;
+
+ s4 += s16 * 666643;
+ s5 += s16 * 470296;
+ s6 += s16 * 654183;
+ s7 -= s16 * 997805;
+ s8 += s16 * 136657;
+ s9 -= s16 * 683901;
+ s16 = 0;
+
+ s3 += s15 * 666643;
+ s4 += s15 * 470296;
+ s5 += s15 * 654183;
+ s6 -= s15 * 997805;
+ s7 += s15 * 136657;
+ s8 -= s15 * 683901;
+ s15 = 0;
+
+ s2 += s14 * 666643;
+ s3 += s14 * 470296;
+ s4 += s14 * 654183;
+ s5 -= s14 * 997805;
+ s6 += s14 * 136657;
+ s7 -= s14 * 683901;
+ s14 = 0;
+
+ s1 += s13 * 666643;
+ s2 += s13 * 470296;
+ s3 += s13 * 654183;
+ s4 -= s13 * 997805;
+ s5 += s13 * 136657;
+ s6 -= s13 * 683901;
+ s13 = 0;
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= SHL64(carry0,21);
+ carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= SHL64(carry2,21);
+ carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= SHL64(carry4,21);
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21);
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21);
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21);
+
+ carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= SHL64(carry1,21);
+ carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= SHL64(carry3,21);
+ carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= SHL64(carry5,21);
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21);
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21);
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21);
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21; s1 += carry0; s0 -= SHL64(carry0,21);
+ carry1 = s1 >> 21; s2 += carry1; s1 -= SHL64(carry1,21);
+ carry2 = s2 >> 21; s3 += carry2; s2 -= SHL64(carry2,21);
+ carry3 = s3 >> 21; s4 += carry3; s3 -= SHL64(carry3,21);
+ carry4 = s4 >> 21; s5 += carry4; s4 -= SHL64(carry4,21);
+ carry5 = s5 >> 21; s6 += carry5; s5 -= SHL64(carry5,21);
+ carry6 = s6 >> 21; s7 += carry6; s6 -= SHL64(carry6,21);
+ carry7 = s7 >> 21; s8 += carry7; s7 -= SHL64(carry7,21);
+ carry8 = s8 >> 21; s9 += carry8; s8 -= SHL64(carry8,21);
+ carry9 = s9 >> 21; s10 += carry9; s9 -= SHL64(carry9,21);
+ carry10 = s10 >> 21; s11 += carry10; s10 -= SHL64(carry10,21);
+ carry11 = s11 >> 21; s12 += carry11; s11 -= SHL64(carry11,21);
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21; s1 += carry0; s0 -= SHL64(carry0,21);
+ carry1 = s1 >> 21; s2 += carry1; s1 -= SHL64(carry1,21);
+ carry2 = s2 >> 21; s3 += carry2; s2 -= SHL64(carry2,21);
+ carry3 = s3 >> 21; s4 += carry3; s3 -= SHL64(carry3,21);
+ carry4 = s4 >> 21; s5 += carry4; s4 -= SHL64(carry4,21);
+ carry5 = s5 >> 21; s6 += carry5; s5 -= SHL64(carry5,21);
+ carry6 = s6 >> 21; s7 += carry6; s6 -= SHL64(carry6,21);
+ carry7 = s7 >> 21; s8 += carry7; s7 -= SHL64(carry7,21);
+ carry8 = s8 >> 21; s9 += carry8; s8 -= SHL64(carry8,21);
+ carry9 = s9 >> 21; s10 += carry9; s9 -= SHL64(carry9,21);
+ carry10 = s10 >> 21; s11 += carry10; s10 -= SHL64(carry10,21);
+
+ s[0] = s0 >> 0;
+ s[1] = s0 >> 8;
+ s[2] = (s0 >> 16) | SHL64(s1,5);
+ s[3] = s1 >> 3;
+ s[4] = s1 >> 11;
+ s[5] = (s1 >> 19) | SHL64(s2,2);
+ s[6] = s2 >> 6;
+ s[7] = (s2 >> 14) | SHL64(s3,7);
+ s[8] = s3 >> 1;
+ s[9] = s3 >> 9;
+ s[10] = (s3 >> 17) | SHL64(s4,4);
+ s[11] = s4 >> 4;
+ s[12] = s4 >> 12;
+ s[13] = (s4 >> 20) | SHL64(s5,1);
+ s[14] = s5 >> 7;
+ s[15] = (s5 >> 15) | SHL64(s6,6);
+ s[16] = s6 >> 2;
+ s[17] = s6 >> 10;
+ s[18] = (s6 >> 18) | SHL64(s7,3);
+ s[19] = s7 >> 5;
+ s[20] = s7 >> 13;
+ s[21] = s8 >> 0;
+ s[22] = s8 >> 8;
+ s[23] = (s8 >> 16) | SHL64(s9,5);
+ s[24] = s9 >> 3;
+ s[25] = s9 >> 11;
+ s[26] = (s9 >> 19) | SHL64(s10,2);
+ s[27] = s10 >> 6;
+ s[28] = (s10 >> 14) | SHL64(s11,7);
+ s[29] = s11 >> 1;
+ s[30] = s11 >> 9;
+ s[31] = s11 >> 17;
+}
diff --git a/src/ext/ed25519/ref10/sc_reduce.c b/src/ext/ed25519/ref10/sc_reduce.c
new file mode 100644
index 0000000000..c5afa53741
--- /dev/null
+++ b/src/ext/ed25519/ref10/sc_reduce.c
@@ -0,0 +1,275 @@
+#include "sc.h"
+#include "crypto_int64.h"
+#include "crypto_uint32.h"
+#include "crypto_uint64.h"
+
+static crypto_uint64 load_3(const unsigned char *in)
+{
+ crypto_uint64 result;
+ result = (crypto_uint64) in[0];
+ result |= ((crypto_uint64) in[1]) << 8;
+ result |= ((crypto_uint64) in[2]) << 16;
+ return result;
+}
+
+static crypto_uint64 load_4(const unsigned char *in)
+{
+ crypto_uint64 result;
+ result = (crypto_uint64) in[0];
+ result |= ((crypto_uint64) in[1]) << 8;
+ result |= ((crypto_uint64) in[2]) << 16;
+ result |= ((crypto_uint64) in[3]) << 24;
+ return result;
+}
+
+/*
+Input:
+ s[0]+256*s[1]+...+256^63*s[63] = s
+
+Output:
+ s[0]+256*s[1]+...+256^31*s[31] = s mod l
+ where l = 2^252 + 27742317777372353535851937790883648493.
+ Overwrites s in place.
+*/
+
+void sc_reduce(unsigned char *s)
+{
+ crypto_int64 s0 = 2097151 & load_3(s);
+ crypto_int64 s1 = 2097151 & (load_4(s + 2) >> 5);
+ crypto_int64 s2 = 2097151 & (load_3(s + 5) >> 2);
+ crypto_int64 s3 = 2097151 & (load_4(s + 7) >> 7);
+ crypto_int64 s4 = 2097151 & (load_4(s + 10) >> 4);
+ crypto_int64 s5 = 2097151 & (load_3(s + 13) >> 1);
+ crypto_int64 s6 = 2097151 & (load_4(s + 15) >> 6);
+ crypto_int64 s7 = 2097151 & (load_3(s + 18) >> 3);
+ crypto_int64 s8 = 2097151 & load_3(s + 21);
+ crypto_int64 s9 = 2097151 & (load_4(s + 23) >> 5);
+ crypto_int64 s10 = 2097151 & (load_3(s + 26) >> 2);
+ crypto_int64 s11 = 2097151 & (load_4(s + 28) >> 7);
+ crypto_int64 s12 = 2097151 & (load_4(s + 31) >> 4);
+ crypto_int64 s13 = 2097151 & (load_3(s + 34) >> 1);
+ crypto_int64 s14 = 2097151 & (load_4(s + 36) >> 6);
+ crypto_int64 s15 = 2097151 & (load_3(s + 39) >> 3);
+ crypto_int64 s16 = 2097151 & load_3(s + 42);
+ crypto_int64 s17 = 2097151 & (load_4(s + 44) >> 5);
+ crypto_int64 s18 = 2097151 & (load_3(s + 47) >> 2);
+ crypto_int64 s19 = 2097151 & (load_4(s + 49) >> 7);
+ crypto_int64 s20 = 2097151 & (load_4(s + 52) >> 4);
+ crypto_int64 s21 = 2097151 & (load_3(s + 55) >> 1);
+ crypto_int64 s22 = 2097151 & (load_4(s + 57) >> 6);
+ crypto_int64 s23 = (load_4(s + 60) >> 3);
+ crypto_int64 carry0;
+ crypto_int64 carry1;
+ crypto_int64 carry2;
+ crypto_int64 carry3;
+ crypto_int64 carry4;
+ crypto_int64 carry5;
+ crypto_int64 carry6;
+ crypto_int64 carry7;
+ crypto_int64 carry8;
+ crypto_int64 carry9;
+ crypto_int64 carry10;
+ crypto_int64 carry11;
+ crypto_int64 carry12;
+ crypto_int64 carry13;
+ crypto_int64 carry14;
+ crypto_int64 carry15;
+ crypto_int64 carry16;
+
+ s11 += s23 * 666643;
+ s12 += s23 * 470296;
+ s13 += s23 * 654183;
+ s14 -= s23 * 997805;
+ s15 += s23 * 136657;
+ s16 -= s23 * 683901;
+ s23 = 0;
+
+ s10 += s22 * 666643;
+ s11 += s22 * 470296;
+ s12 += s22 * 654183;
+ s13 -= s22 * 997805;
+ s14 += s22 * 136657;
+ s15 -= s22 * 683901;
+ s22 = 0;
+
+ s9 += s21 * 666643;
+ s10 += s21 * 470296;
+ s11 += s21 * 654183;
+ s12 -= s21 * 997805;
+ s13 += s21 * 136657;
+ s14 -= s21 * 683901;
+ s21 = 0;
+
+ s8 += s20 * 666643;
+ s9 += s20 * 470296;
+ s10 += s20 * 654183;
+ s11 -= s20 * 997805;
+ s12 += s20 * 136657;
+ s13 -= s20 * 683901;
+ s20 = 0;
+
+ s7 += s19 * 666643;
+ s8 += s19 * 470296;
+ s9 += s19 * 654183;
+ s10 -= s19 * 997805;
+ s11 += s19 * 136657;
+ s12 -= s19 * 683901;
+ s19 = 0;
+
+ s6 += s18 * 666643;
+ s7 += s18 * 470296;
+ s8 += s18 * 654183;
+ s9 -= s18 * 997805;
+ s10 += s18 * 136657;
+ s11 -= s18 * 683901;
+ s18 = 0;
+
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21);
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21);
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21);
+ carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= SHL64(carry12,21);
+ carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= SHL64(carry14,21);
+ carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= SHL64(carry16,21);
+
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21);
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21);
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21);
+ carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= SHL64(carry13,21);
+ carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= SHL64(carry15,21);
+
+ s5 += s17 * 666643;
+ s6 += s17 * 470296;
+ s7 += s17 * 654183;
+ s8 -= s17 * 997805;
+ s9 += s17 * 136657;
+ s10 -= s17 * 683901;
+ s17 = 0;
+
+ s4 += s16 * 666643;
+ s5 += s16 * 470296;
+ s6 += s16 * 654183;
+ s7 -= s16 * 997805;
+ s8 += s16 * 136657;
+ s9 -= s16 * 683901;
+ s16 = 0;
+
+ s3 += s15 * 666643;
+ s4 += s15 * 470296;
+ s5 += s15 * 654183;
+ s6 -= s15 * 997805;
+ s7 += s15 * 136657;
+ s8 -= s15 * 683901;
+ s15 = 0;
+
+ s2 += s14 * 666643;
+ s3 += s14 * 470296;
+ s4 += s14 * 654183;
+ s5 -= s14 * 997805;
+ s6 += s14 * 136657;
+ s7 -= s14 * 683901;
+ s14 = 0;
+
+ s1 += s13 * 666643;
+ s2 += s13 * 470296;
+ s3 += s13 * 654183;
+ s4 -= s13 * 997805;
+ s5 += s13 * 136657;
+ s6 -= s13 * 683901;
+ s13 = 0;
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= SHL64(carry0,21);
+ carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= SHL64(carry2,21);
+ carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= SHL64(carry4,21);
+ carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= SHL64(carry6,21);
+ carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= SHL64(carry8,21);
+ carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= SHL64(carry10,21);
+
+ carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= SHL64(carry1,21);
+ carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= SHL64(carry3,21);
+ carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= SHL64(carry5,21);
+ carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= SHL64(carry7,21);
+ carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= SHL64(carry9,21);
+ carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= SHL64(carry11,21);
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21; s1 += carry0; s0 -= SHL64(carry0,21);
+ carry1 = s1 >> 21; s2 += carry1; s1 -= SHL64(carry1,21);
+ carry2 = s2 >> 21; s3 += carry2; s2 -= SHL64(carry2,21);
+ carry3 = s3 >> 21; s4 += carry3; s3 -= SHL64(carry3,21);
+ carry4 = s4 >> 21; s5 += carry4; s4 -= SHL64(carry4,21);
+ carry5 = s5 >> 21; s6 += carry5; s5 -= SHL64(carry5,21);
+ carry6 = s6 >> 21; s7 += carry6; s6 -= SHL64(carry6,21);
+ carry7 = s7 >> 21; s8 += carry7; s7 -= SHL64(carry7,21);
+ carry8 = s8 >> 21; s9 += carry8; s8 -= SHL64(carry8,21);
+ carry9 = s9 >> 21; s10 += carry9; s9 -= SHL64(carry9,21);
+ carry10 = s10 >> 21; s11 += carry10; s10 -= SHL64(carry10,21);
+ carry11 = s11 >> 21; s12 += carry11; s11 -= SHL64(carry11,21);
+
+ s0 += s12 * 666643;
+ s1 += s12 * 470296;
+ s2 += s12 * 654183;
+ s3 -= s12 * 997805;
+ s4 += s12 * 136657;
+ s5 -= s12 * 683901;
+ s12 = 0;
+
+ carry0 = s0 >> 21; s1 += carry0; s0 -= SHL64(carry0,21);
+ carry1 = s1 >> 21; s2 += carry1; s1 -= SHL64(carry1,21);
+ carry2 = s2 >> 21; s3 += carry2; s2 -= SHL64(carry2,21);
+ carry3 = s3 >> 21; s4 += carry3; s3 -= SHL64(carry3,21);
+ carry4 = s4 >> 21; s5 += carry4; s4 -= SHL64(carry4,21);
+ carry5 = s5 >> 21; s6 += carry5; s5 -= SHL64(carry5,21);
+ carry6 = s6 >> 21; s7 += carry6; s6 -= SHL64(carry6,21);
+ carry7 = s7 >> 21; s8 += carry7; s7 -= SHL64(carry7,21);
+ carry8 = s8 >> 21; s9 += carry8; s8 -= SHL64(carry8,21);
+ carry9 = s9 >> 21; s10 += carry9; s9 -= SHL64(carry9,21);
+ carry10 = s10 >> 21; s11 += carry10; s10 -= SHL64(carry10,21);
+
+ s[0] = s0 >> 0;
+ s[1] = s0 >> 8;
+ s[2] = (s0 >> 16) | SHL64(s1,5);
+ s[3] = s1 >> 3;
+ s[4] = s1 >> 11;
+ s[5] = (s1 >> 19) | SHL64(s2,2);
+ s[6] = s2 >> 6;
+ s[7] = (s2 >> 14) | SHL64(s3,7);
+ s[8] = s3 >> 1;
+ s[9] = s3 >> 9;
+ s[10] = (s3 >> 17) | SHL64(s4,4);
+ s[11] = s4 >> 4;
+ s[12] = s4 >> 12;
+ s[13] = (s4 >> 20) | SHL64(s5,1);
+ s[14] = s5 >> 7;
+ s[15] = (s5 >> 15) | SHL64(s6,6);
+ s[16] = s6 >> 2;
+ s[17] = s6 >> 10;
+ s[18] = (s6 >> 18) | SHL64(s7,3);
+ s[19] = s7 >> 5;
+ s[20] = s7 >> 13;
+ s[21] = s8 >> 0;
+ s[22] = s8 >> 8;
+ s[23] = (s8 >> 16) | SHL64(s9,5);
+ s[24] = s9 >> 3;
+ s[25] = s9 >> 11;
+ s[26] = (s9 >> 19) | SHL64(s10,2);
+ s[27] = s10 >> 6;
+ s[28] = (s10 >> 14) | SHL64(s11,7);
+ s[29] = s11 >> 1;
+ s[30] = s11 >> 9;
+ s[31] = s11 >> 17;
+}
diff --git a/src/ext/ed25519/ref10/sign.c b/src/ext/ed25519/ref10/sign.c
new file mode 100644
index 0000000000..1190a0fc99
--- /dev/null
+++ b/src/ext/ed25519/ref10/sign.c
@@ -0,0 +1,29 @@
+/* (Modified by Tor to generate detached signatures.) */
+#include <string.h>
+#include "crypto_sign.h"
+#include "crypto_hash_sha512.h"
+#include "ge.h"
+#include "sc.h"
+
+int crypto_sign(
+ unsigned char *sig,
+ const unsigned char *m, size_t mlen,
+ const unsigned char *sk,const unsigned char *pk
+)
+{
+ unsigned char nonce[64];
+ unsigned char hram[64];
+ ge_p3 R;
+
+ crypto_hash_sha512_2(nonce, sk+32, 32, m, mlen);
+
+ sc_reduce(nonce);
+ ge_scalarmult_base(&R,nonce);
+ ge_p3_tobytes(sig,&R);
+
+ crypto_hash_sha512_3(hram, sig, 32, pk, 32, m, mlen);
+ sc_reduce(hram);
+ sc_muladd(sig + 32,hram,sk,nonce);
+
+ return 0;
+}
diff --git a/src/ext/ed25519/ref10/sqrtm1.h b/src/ext/ed25519/ref10/sqrtm1.h
new file mode 100644
index 0000000000..d8caa23b6a
--- /dev/null
+++ b/src/ext/ed25519/ref10/sqrtm1.h
@@ -0,0 +1 @@
+-32595792,-7943725,9377950,3500415,12389472,-272473,-25146209,-2005654,326686,11406482
diff --git a/src/ext/ed25519/ref10/sqrtm1.py b/src/ext/ed25519/ref10/sqrtm1.py
new file mode 100644
index 0000000000..9a47fbc12a
--- /dev/null
+++ b/src/ext/ed25519/ref10/sqrtm1.py
@@ -0,0 +1,28 @@
+q = 2**255 - 19
+
+def expmod(b,e,m):
+ if e == 0: return 1
+ t = expmod(b,e/2,m)**2 % m
+ if e & 1: t = (t*b) % m
+ return t
+
+def inv(x):
+ return expmod(x,q-2,q)
+
+def radix255(x):
+ x = x % q
+ if x + x > q: x -= q
+ x = [x,0,0,0,0,0,0,0,0,0]
+ bits = [26,25,26,25,26,25,26,25,26,25]
+ for i in range(9):
+ carry = (x[i] + 2**(bits[i]-1)) / 2**bits[i]
+ x[i] -= carry * 2**bits[i]
+ x[i + 1] += carry
+ result = ""
+ for i in range(9):
+ result = result+str(x[i])+","
+ result = result+str(x[9])
+ return result
+
+I = expmod(2,(q-1)/4,q)
+print radix255(I)
diff --git a/src/ext/include.am b/src/ext/include.am
index 26e194e88e..576fd4efb8 100644
--- a/src/ext/include.am
+++ b/src/ext/include.am
@@ -15,4 +15,80 @@ EXTHEADERS = \
noinst_HEADERS+= $(EXTHEADERS)
+src_ext_ed25519_ref10_libed25519_ref10_a_CFLAGS=
+
+src_ext_ed25519_ref10_libed25519_ref10_a_SOURCES= \
+ src/ext/ed25519/ref10/fe_0.c \
+ src/ext/ed25519/ref10/fe_1.c \
+ src/ext/ed25519/ref10/fe_add.c \
+ src/ext/ed25519/ref10/fe_cmov.c \
+ src/ext/ed25519/ref10/fe_copy.c \
+ src/ext/ed25519/ref10/fe_frombytes.c \
+ src/ext/ed25519/ref10/fe_invert.c \
+ src/ext/ed25519/ref10/fe_isnegative.c \
+ src/ext/ed25519/ref10/fe_isnonzero.c \
+ src/ext/ed25519/ref10/fe_mul.c \
+ src/ext/ed25519/ref10/fe_neg.c \
+ src/ext/ed25519/ref10/fe_pow22523.c \
+ src/ext/ed25519/ref10/fe_sq.c \
+ src/ext/ed25519/ref10/fe_sq2.c \
+ src/ext/ed25519/ref10/fe_sub.c \
+ src/ext/ed25519/ref10/fe_tobytes.c \
+ src/ext/ed25519/ref10/ge_add.c \
+ src/ext/ed25519/ref10/ge_double_scalarmult.c \
+ src/ext/ed25519/ref10/ge_frombytes.c \
+ src/ext/ed25519/ref10/ge_madd.c \
+ src/ext/ed25519/ref10/ge_msub.c \
+ src/ext/ed25519/ref10/ge_p1p1_to_p2.c \
+ src/ext/ed25519/ref10/ge_p1p1_to_p3.c \
+ src/ext/ed25519/ref10/ge_p2_0.c \
+ src/ext/ed25519/ref10/ge_p2_dbl.c \
+ src/ext/ed25519/ref10/ge_p3_0.c \
+ src/ext/ed25519/ref10/ge_p3_dbl.c \
+ src/ext/ed25519/ref10/ge_p3_to_cached.c \
+ src/ext/ed25519/ref10/ge_p3_to_p2.c \
+ src/ext/ed25519/ref10/ge_p3_tobytes.c \
+ src/ext/ed25519/ref10/ge_precomp_0.c \
+ src/ext/ed25519/ref10/ge_scalarmult_base.c \
+ src/ext/ed25519/ref10/ge_sub.c \
+ src/ext/ed25519/ref10/ge_tobytes.c \
+ src/ext/ed25519/ref10/keypair.c \
+ src/ext/ed25519/ref10/open.c \
+ src/ext/ed25519/ref10/sc_muladd.c \
+ src/ext/ed25519/ref10/sc_reduce.c \
+ src/ext/ed25519/ref10/sign.c \
+ src/ext/ed25519/ref10/keyconv.c \
+ src/ext/ed25519/ref10/blinding.c
+
+ED25519_REF10_HDRS = \
+ src/ext/ed25519/ref10/api.h \
+ src/ext/ed25519/ref10/base.h \
+ src/ext/ed25519/ref10/base2.h \
+ src/ext/ed25519/ref10/crypto_hash_sha512.h \
+ src/ext/ed25519/ref10/crypto_int32.h \
+ src/ext/ed25519/ref10/crypto_int64.h \
+ src/ext/ed25519/ref10/crypto_sign.h \
+ src/ext/ed25519/ref10/crypto_uint32.h \
+ src/ext/ed25519/ref10/crypto_uint64.h \
+ src/ext/ed25519/ref10/crypto_verify_32.h \
+ src/ext/ed25519/ref10/d.h \
+ src/ext/ed25519/ref10/d2.h \
+ src/ext/ed25519/ref10/ed25519_ref10.h \
+ src/ext/ed25519/ref10/fe.h \
+ src/ext/ed25519/ref10/ge.h \
+ src/ext/ed25519/ref10/ge_add.h \
+ src/ext/ed25519/ref10/ge_madd.h \
+ src/ext/ed25519/ref10/ge_msub.h \
+ src/ext/ed25519/ref10/ge_p2_dbl.h \
+ src/ext/ed25519/ref10/ge_sub.h \
+ src/ext/ed25519/ref10/pow22523.h \
+ src/ext/ed25519/ref10/pow225521.h \
+ src/ext/ed25519/ref10/randombytes.h \
+ src/ext/ed25519/ref10/sc.h \
+ src/ext/ed25519/ref10/sqrtm1.h
+
+noinst_HEADERS += $(ED25519_REF10_HDRS)
+
+LIBED25519_REF10=src/ext/ed25519/ref10/libed25519_ref10.a
+noinst_LIBRARIES += $(LIBED25519_REF10)
diff --git a/src/ext/trunnel/trunnel-impl.h b/src/ext/trunnel/trunnel-impl.h
new file mode 100644
index 0000000000..c88ee3988e
--- /dev/null
+++ b/src/ext/trunnel/trunnel-impl.h
@@ -0,0 +1,310 @@
+/* trunnel-impl.h -- copied from Trunnel v1.2
+ * https://gitweb.torproject.org/trunnel.git
+ * You probably shouldn't edit this file.
+ */
+/* trunnel-impl.h -- Implementation helpers for trunnel, included by
+ * generated trunnel files
+ *
+ * Copyright 2014, The Tor Project, Inc.
+ * See license at the end of this file for copying information.
+ */
+
+#ifndef TRUNNEL_IMPL_H_INCLUDED_
+#define TRUNNEL_IMPL_H_INCLUDED_
+#include "trunnel.h"
+#include <assert.h>
+#include <string.h>
+#ifdef TRUNNEL_LOCAL_H
+#include "trunnel-local.h"
+#endif
+
+#ifdef _MSC_VER
+#define uint8_t unsigned char
+#define uint16_t unsigned short
+#define uint32_t unsigned int
+#define uint64_t unsigned __int64
+#define inline __inline
+#else
+#include <stdint.h>
+#endif
+
+#ifdef _WIN32
+uint32_t trunnel_htonl(uint32_t a);
+uint32_t trunnel_ntohl(uint32_t a);
+uint16_t trunnel_htons(uint16_t a);
+uint16_t trunnel_ntohs(uint16_t a);
+#else
+#include <arpa/inet.h>
+#define trunnel_htonl(x) htonl(x)
+#define trunnel_htons(x) htons(x)
+#define trunnel_ntohl(x) ntohl(x)
+#define trunnel_ntohs(x) ntohs(x)
+#endif
+uint64_t trunnel_htonll(uint64_t a);
+uint64_t trunnel_ntohll(uint64_t a);
+
+#ifndef trunnel_assert
+#define trunnel_assert(x) assert(x)
+#endif
+
+static inline void
+trunnel_set_uint64(void *p, uint64_t v) {
+ memcpy(p, &v, 8);
+}
+static inline void
+trunnel_set_uint32(void *p, uint32_t v) {
+ memcpy(p, &v, 4);
+}
+static inline void
+trunnel_set_uint16(void *p, uint16_t v) {
+ memcpy(p, &v, 2);
+}
+static inline void
+trunnel_set_uint8(void *p, uint8_t v) {
+ memcpy(p, &v, 1);
+}
+
+static inline uint64_t
+trunnel_get_uint64(const void *p) {
+ uint64_t x;
+ memcpy(&x, p, 8);
+ return x;
+}
+static inline uint32_t
+trunnel_get_uint32(const void *p) {
+ uint32_t x;
+ memcpy(&x, p, 4);
+ return x;
+}
+static inline uint16_t
+trunnel_get_uint16(const void *p) {
+ uint16_t x;
+ memcpy(&x, p, 2);
+ return x;
+}
+static inline uint8_t
+trunnel_get_uint8(const void *p) {
+ return *(const uint8_t*)p;
+}
+
+
+#ifdef TRUNNEL_DEBUG_FAILING_ALLOC
+extern int trunnel_provoke_alloc_failure;
+
+static inline void *
+trunnel_malloc(size_t n)
+{
+ if (trunnel_provoke_alloc_failure) {
+ if (--trunnel_provoke_alloc_failure == 0)
+ return NULL;
+ }
+ return malloc(n);
+}
+static inline void *
+trunnel_calloc(size_t a, size_t b)
+{
+ if (trunnel_provoke_alloc_failure) {
+ if (--trunnel_provoke_alloc_failure == 0)
+ return NULL;
+ }
+ return calloc(a,b);
+}
+static inline char *
+trunnel_strdup(const char *s)
+{
+ if (trunnel_provoke_alloc_failure) {
+ if (--trunnel_provoke_alloc_failure == 0)
+ return NULL;
+ }
+ return strdup(s);
+}
+#else
+#ifndef trunnel_malloc
+#define trunnel_malloc(x) (malloc((x)))
+#endif
+#ifndef trunnel_calloc
+#define trunnel_calloc(a,b) (calloc((a),(b)))
+#endif
+#ifndef trunnel_strdup
+#define trunnel_strdup(s) (strdup((s)))
+#endif
+#endif
+
+#ifndef trunnel_realloc
+#define trunnel_realloc(a,b) realloc((a),(b))
+#endif
+
+#ifndef trunnel_free_
+#define trunnel_free_(x) (free(x))
+#endif
+#define trunnel_free(x) ((x) ? (trunnel_free_(x),0) : (0))
+
+#ifndef trunnel_abort
+#define trunnel_abort() abort()
+#endif
+
+#ifndef trunnel_memwipe
+#define trunnel_memwipe(mem, len) ((void)0)
+#define trunnel_wipestr(s) ((void)0)
+#else
+#define trunnel_wipestr(s) do { \
+ if (s) \
+ trunnel_memwipe(s, strlen(s)); \
+ } while (0)
+#endif
+
+/* ====== dynamic arrays ======== */
+
+#ifdef NDEBUG
+#define TRUNNEL_DYNARRAY_GET(da, n) \
+ ((da)->elts_[(n)])
+#else
+/** Return the 'n'th element of 'da'. */
+#define TRUNNEL_DYNARRAY_GET(da, n) \
+ (((n) >= (da)->n_ ? (trunnel_abort(),0) : 0), (da)->elts_[(n)])
+#endif
+
+/** Change the 'n'th element of 'da' to 'v'. */
+#define TRUNNEL_DYNARRAY_SET(da, n, v) do { \
+ trunnel_assert((n) < (da)->n_); \
+ (da)->elts_[(n)] = (v); \
+ } while (0)
+
+/** Expand the dynamic array 'da' of 'elttype' so that it can hold at least
+ * 'howmanymore' elements than its current capacity. Always tries to increase
+ * the length of the array. On failure, run the code in 'on_fail' and goto
+ * trunnel_alloc_failed. */
+#define TRUNNEL_DYNARRAY_EXPAND(elttype, da, howmanymore, on_fail) do { \
+ elttype *newarray; \
+ newarray = trunnel_dynarray_expand(&(da)->allocated_, \
+ (da)->elts_, (howmanymore), \
+ sizeof(elttype)); \
+ if (newarray == NULL) { \
+ on_fail; \
+ goto trunnel_alloc_failed; \
+ } \
+ (da)->elts_ = newarray; \
+ } while (0)
+
+/** Add 'v' to the end of the dynamic array 'da' of 'elttype', expanding it if
+ * necessary. code in 'on_fail' and goto trunnel_alloc_failed. */
+#define TRUNNEL_DYNARRAY_ADD(elttype, da, v, on_fail) do { \
+ if ((da)->n_ == (da)->allocated_) { \
+ TRUNNEL_DYNARRAY_EXPAND(elttype, da, 1, on_fail); \
+ } \
+ (da)->elts_[(da)->n_++] = (v); \
+ } while (0)
+
+/** Return the number of elements in 'da'. */
+#define TRUNNEL_DYNARRAY_LEN(da) ((da)->n_)
+
+/** Remove all storage held by 'da' and set it to be empty. Does not free
+ * storage held by the elements themselves. */
+#define TRUNNEL_DYNARRAY_CLEAR(da) do { \
+ trunnel_free((da)->elts_); \
+ (da)->elts_ = NULL; \
+ (da)->n_ = (da)->allocated_ = 0; \
+ } while (0)
+
+/** Remove all storage held by 'da' and set it to be empty. Does not free
+ * storage held by the elements themselves. */
+#define TRUNNEL_DYNARRAY_WIPE(da) do { \
+ trunnel_memwipe((da)->elts_, (da)->allocated_ * sizeof((da)->elts_[0])); \
+ } while (0)
+
+/** Helper: wraps or implements an OpenBSD-style reallocarray. Behaves
+ * as realloc(a, x*y), but verifies that no overflow will occur in the
+ * multiplication. Returns NULL on failure. */
+#ifndef trunnel_reallocarray
+void *trunnel_reallocarray(void *a, size_t x, size_t y);
+#endif
+
+/** Helper to expand a dynamic array. Behaves as TRUNNEL_DYNARRAY_EXPAND(),
+ * taking the array of elements in 'ptr', a pointer to thethe current number
+ * of allocated elements in allocated_p, the minimum numbeer of elements to
+ * add in 'howmanymore', and the size of a single element in 'eltsize'.
+ *
+ * On success, adjust *allocated_p, and return the new value for the array of
+ * elements. On failure, adjust nothing and return NULL.
+ */
+void *trunnel_dynarray_expand(size_t *allocated_p, void *ptr,
+ size_t howmanymore, size_t eltsize);
+
+/** Type for a function to free members of a dynarray of pointers. */
+typedef void (*trunnel_free_fn_t)(void *);
+
+/**
+ * Helper to change the length of a dynamic array. Takes pointers to the
+ * current allocated and n fields of the array in 'allocated_p' and 'len_p',
+ * and the current array of elements in 'ptr'; takes the length of a single
+ * element in 'eltsize'. Changes the length to 'newlen'. If 'newlen' is
+ * greater than the current length, pads the new elements with 0. If newlen
+ * is less than the current length, and free_fn is non-NULL, treat the
+ * array as an array of void *, and invoke free_fn() on each removed element.
+ *
+ * On success, adjust *allocated_p and *len_p, and return the new value for
+ * the array of elements. On failure, adjust nothing, set *errcode_ptr to 1,
+ * and return NULL.
+ */
+void *trunnel_dynarray_setlen(size_t *allocated_p, size_t *len_p,
+ void *ptr, size_t newlen,
+ size_t eltsize, trunnel_free_fn_t free_fn,
+ uint8_t *errcode_ptr);
+
+/**
+ * Helper: return a pointer to the value of 'str' as a NUL-terminated string.
+ * Might have to reallocate the storage for 'str' in order to fit in the final
+ * NUL character. On allocation failure, return NULL.
+ */
+const char *trunnel_string_getstr(trunnel_string_t *str);
+
+/**
+ * Helper: change the contents of 'str' to hold the 'len'-byte string in
+ * 'inp'. Adjusts the storage to have a terminating NUL that doesn't count
+ * towards the length of the string. On success, return 0. On failure, set
+ * *errcode_ptr to 1 and return -1.
+ */
+int trunnel_string_setstr0(trunnel_string_t *str, const char *inp, size_t len,
+ uint8_t *errcode_ptr);
+
+/**
+ * As trunnel_dynarray_setlen, but adjusts a string rather than a dynamic
+ * array, and ensures that the new string is NUL-terminated.
+ */
+int trunnel_string_setlen(trunnel_string_t *str, size_t newlen,
+ uint8_t *errcode_ptr);
+
+#endif
+
+
+/*
+Copyright 2014 The Tor Project, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+ * Neither the names of the copyright owners nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
diff --git a/src/ext/trunnel/trunnel.c b/src/ext/trunnel/trunnel.c
new file mode 100644
index 0000000000..da4885ca01
--- /dev/null
+++ b/src/ext/trunnel/trunnel.c
@@ -0,0 +1,246 @@
+/* trunnel.c -- copied from Trunnel v1.2
+ * https://gitweb.torproject.org/trunnel.git
+ * You probably shouldn't edit this file.
+ */
+/* trunnel.c -- Helper functions to implement trunnel.
+ *
+ * Copyright 2014, The Tor Project, Inc.
+ * See license at the end of this file for copying information.
+ *
+ * See trunnel-impl.h for documentation of these functions.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "trunnel-impl.h"
+
+#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
+ __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define IS_LITTLE_ENDIAN 1
+#elif defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) && \
+ BYTE_ORDER == __ORDER_LITTLE_ENDIAN
+# define IS_LITTLE_ENDIAN 1
+#elif defined(_WIN32)
+# define IS_LITTLE_ENDIAN 1
+#elif defined(__APPLE__)
+# include <libkern/OSByteOrder.h>
+# define BSWAP64(x) OSSwapLittleToHostInt64(x)
+#elif defined(sun) || defined(__sun)
+# include <sys/byteorder.h>
+# ifndef _BIG_ENDIAN
+# define IS_LITTLE_ENDIAN
+# endif
+#else
+# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+# include <sys/endian.h>
+# else
+# include <endian.h>
+# endif
+# if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
+ __BYTE_ORDER == __LITTLE_ENDIAN
+# define IS_LITTLE_ENDIAN
+# endif
+#endif
+
+#ifdef _WIN32
+uint16_t
+trunnel_htons(uint16_t s)
+{
+ return (s << 8) | (s >> 8);
+}
+uint16_t
+trunnel_ntohs(uint16_t s)
+{
+ return (s << 8) | (s >> 8);
+}
+uint32_t
+trunnel_htonl(uint32_t s)
+{
+ return (s << 24) |
+ ((s << 8)&0xff0000) |
+ ((s >> 8)&0xff00) |
+ (s >> 24);
+}
+uint32_t
+trunnel_ntohl(uint32_t s)
+{
+ return (s << 24) |
+ ((s << 8)&0xff0000) |
+ ((s >> 8)&0xff00) |
+ (s >> 24);
+}
+#endif
+
+uint64_t
+trunnel_htonll(uint64_t a)
+{
+#ifdef IS_LITTLE_ENDIAN
+ return trunnel_htonl(a>>32) | (((uint64_t)trunnel_htonl(a))<<32);
+#else
+ return a;
+#endif
+}
+
+uint64_t
+trunnel_ntohll(uint64_t a)
+{
+ return trunnel_htonll(a);
+}
+
+#ifdef TRUNNEL_DEBUG_FAILING_ALLOC
+/** Used for debugging and running tricky test cases: Makes the nth
+ * memoryation allocation call from now fail.
+ */
+int trunnel_provoke_alloc_failure = 0;
+#endif
+
+void *
+trunnel_dynarray_expand(size_t *allocated_p, void *ptr,
+ size_t howmanymore, size_t eltsize)
+{
+ size_t newsize = howmanymore + *allocated_p;
+ void *newarray = NULL;
+ if (newsize < 8)
+ newsize = 8;
+ if (newsize < *allocated_p * 2)
+ newsize = *allocated_p * 2;
+ if (newsize <= *allocated_p || newsize < howmanymore)
+ return NULL;
+ newarray = trunnel_reallocarray(ptr, newsize, eltsize);
+ if (newarray == NULL)
+ return NULL;
+
+ *allocated_p = newsize;
+ return newarray;
+}
+
+#ifndef trunnel_reallocarray
+void *
+trunnel_reallocarray(void *a, size_t x, size_t y)
+{
+#ifdef TRUNNEL_DEBUG_FAILING_ALLOC
+ if (trunnel_provoke_alloc_failure) {
+ if (--trunnel_provoke_alloc_failure == 0)
+ return NULL;
+ }
+#endif
+ if (x > SIZE_MAX / y)
+ return NULL;
+ return trunnel_realloc(a, x * y);
+}
+#endif
+
+const char *
+trunnel_string_getstr(trunnel_string_t *str)
+{
+ trunnel_assert(str->allocated_ >= str->n_);
+ if (str->allocated_ == str->n_) {
+ TRUNNEL_DYNARRAY_EXPAND(char, str, 1, {});
+ }
+ str->elts_[str->n_] = 0;
+ return str->elts_;
+trunnel_alloc_failed:
+ return NULL;
+}
+
+int
+trunnel_string_setstr0(trunnel_string_t *str, const char *val, size_t len,
+ uint8_t *errcode_ptr)
+{
+ if (len == SIZE_MAX)
+ goto trunnel_alloc_failed;
+ if (str->allocated_ <= len) {
+ TRUNNEL_DYNARRAY_EXPAND(char, str, len + 1 - str->allocated_, {});
+ }
+ memcpy(str->elts_, val, len);
+ str->n_ = len;
+ str->elts_[len] = 0;
+ return 0;
+trunnel_alloc_failed:
+ *errcode_ptr = 1;
+ return -1;
+}
+
+int
+trunnel_string_setlen(trunnel_string_t *str, size_t newlen,
+ uint8_t *errcode_ptr)
+{
+ if (newlen == SIZE_MAX)
+ goto trunnel_alloc_failed;
+ if (str->allocated_ < newlen + 1) {
+ TRUNNEL_DYNARRAY_EXPAND(char, str, newlen + 1 - str->allocated_, {});
+ }
+ if (str->n_ < newlen) {
+ memset(& (str->elts_[str->n_]), 0, (newlen - str->n_));
+ }
+ str->n_ = newlen;
+ str->elts_[newlen] = 0;
+ return 0;
+
+ trunnel_alloc_failed:
+ *errcode_ptr = 1;
+ return -1;
+}
+
+void *
+trunnel_dynarray_setlen(size_t *allocated_p, size_t *len_p,
+ void *ptr, size_t newlen,
+ size_t eltsize, trunnel_free_fn_t free_fn,
+ uint8_t *errcode_ptr)
+{
+ if (*allocated_p < newlen) {
+ void *newptr = trunnel_dynarray_expand(allocated_p, ptr,
+ newlen - *allocated_p, eltsize);
+ if (newptr == NULL)
+ goto trunnel_alloc_failed;
+ ptr = newptr;
+ }
+ if (free_fn && *len_p > newlen) {
+ size_t i;
+ void **elts = (void **) ptr;
+ for (i = newlen; i < *len_p; ++i) {
+ free_fn(elts[i]);
+ elts[i] = NULL;
+ }
+ }
+ if (*len_p < newlen) {
+ memset( ((char*)ptr) + (eltsize * *len_p), 0, (newlen - *len_p) * eltsize);
+ }
+ *len_p = newlen;
+ return ptr;
+ trunnel_alloc_failed:
+ *errcode_ptr = 1;
+ return NULL;
+}
+
+/*
+Copyright 2014 The Tor Project, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+ * Neither the names of the copyright owners nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
diff --git a/src/ext/trunnel/trunnel.h b/src/ext/trunnel/trunnel.h
new file mode 100644
index 0000000000..f51cade03f
--- /dev/null
+++ b/src/ext/trunnel/trunnel.h
@@ -0,0 +1,64 @@
+/* trunnel.h -- copied from Trunnel v1.2
+ * https://gitweb.torproject.org/trunnel.git
+ * You probably shouldn't edit this file.
+ */
+/* trunnel.h -- Public declarations for trunnel, to be included
+ * in trunnel header files.
+
+ * Copyright 2014, The Tor Project, Inc.
+ * See license at the end of this file for copying information.
+ */
+
+#ifndef TRUNNEL_H_INCLUDED_
+#define TRUNNEL_H_INCLUDED_
+
+#include <sys/types.h>
+
+/** Macro to declare a variable-length dynamically allocated array. Trunnel
+ * uses these to store all variable-length arrays. */
+#define TRUNNEL_DYNARRAY_HEAD(name, elttype) \
+ struct name { \
+ size_t n_; \
+ size_t allocated_; \
+ elttype *elts_; \
+ }
+
+/** Initializer for a dynamic array of a given element type. */
+#define TRUNNEL_DYNARRAY_INIT(elttype) { 0, 0, (elttype*)NULL }
+
+/** Typedef used for storing variable-length arrays of char. */
+typedef TRUNNEL_DYNARRAY_HEAD(trunnel_string_st, char) trunnel_string_t;
+
+#endif
+
+/*
+Copyright 2014 The Tor Project, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+ * Neither the names of the copyright owners nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
diff --git a/src/include.am b/src/include.am
index d0693e25b0..c468af3649 100644
--- a/src/include.am
+++ b/src/include.am
@@ -1,7 +1,9 @@
include src/ext/include.am
+include src/trunnel/include.am
include src/common/include.am
include src/or/include.am
include src/test/include.am
include src/tools/include.am
include src/win32/include.am
include src/config/include.am
+
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 033f86288e..9f02824bff 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -55,6 +55,9 @@
* forever.
*/
+static void socks_request_set_socks5_error(socks_request_t *req,
+ socks5_reply_status_t reason);
+
static int parse_socks(const char *data, size_t datalen, socks_request_t *req,
int log_sockstype, int safe_socks, ssize_t *drain_out,
size_t *want_length_out);
@@ -1831,6 +1834,21 @@ fetch_ext_or_command_from_evbuffer(struct evbuffer *buf, ext_or_cmd_t **out)
}
#endif
+/** Create a SOCKS5 reply message with <b>reason</b> in its REP field and
+ * have Tor send it as error response to <b>req</b>.
+ */
+static void
+socks_request_set_socks5_error(socks_request_t *req,
+ socks5_reply_status_t reason)
+{
+ req->replylen = 10;
+ memset(req->reply,0,10);
+
+ req->reply[0] = 0x05; // VER field.
+ req->reply[1] = reason; // REP field.
+ req->reply[3] = 0x01; // ATYP field.
+}
+
/** Implementation helper to implement fetch_from_*_socks. Instead of looking
* at a buffer's contents, we look at the <b>datalen</b> bytes of data in
* <b>data</b>. Instead of removing data from the buffer, we set
@@ -1966,6 +1984,8 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
req->command != SOCKS_COMMAND_RESOLVE &&
req->command != SOCKS_COMMAND_RESOLVE_PTR) {
/* not a connect or resolve or a resolve_ptr? we don't support it. */
+ socks_request_set_socks5_error(req,SOCKS5_COMMAND_NOT_SUPPORTED);
+
log_warn(LD_APP,"socks5: command %d not recognized. Rejecting.",
req->command);
return -1;
@@ -1989,6 +2009,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
tor_addr_to_str(tmpbuf, &destaddr, sizeof(tmpbuf), 1);
if (strlen(tmpbuf)+1 > MAX_SOCKS_ADDR_LEN) {
+ socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
log_warn(LD_APP,
"socks5 IP takes %d bytes, which doesn't fit in %d. "
"Rejecting.",
@@ -2001,14 +2022,18 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
if (req->command != SOCKS_COMMAND_RESOLVE_PTR &&
!addressmap_have_mapping(req->address,0)) {
log_unsafe_socks_warning(5, req->address, req->port, safe_socks);
- if (safe_socks)
+ if (safe_socks) {
+ socks_request_set_socks5_error(req, SOCKS5_NOT_ALLOWED);
return -1;
+ }
}
return 1;
}
case 3: /* fqdn */
log_debug(LD_APP,"socks5: fqdn address type");
if (req->command == SOCKS_COMMAND_RESOLVE_PTR) {
+ socks_request_set_socks5_error(req,
+ SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
log_warn(LD_APP, "socks5 received RESOLVE_PTR command with "
"hostname type. Rejecting.");
return -1;
@@ -2019,6 +2044,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
return 0; /* not yet */
}
if (len+1 > MAX_SOCKS_ADDR_LEN) {
+ socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
log_warn(LD_APP,
"socks5 hostname is %d bytes, which doesn't fit in "
"%d. Rejecting.", len+1,MAX_SOCKS_ADDR_LEN);
@@ -2029,6 +2055,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
req->port = ntohs(get_uint16(data+5+len));
*drain_out = 5+len+2;
if (!tor_strisprint(req->address) || strchr(req->address,'\"')) {
+ socks_request_set_socks5_error(req, SOCKS5_GENERAL_ERROR);
log_warn(LD_PROTOCOL,
"Your application (using socks5 to port %d) gave Tor "
"a malformed hostname: %s. Rejecting the connection.",
@@ -2042,6 +2069,8 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req,
"necessary. This is good.", req->port);
return 1;
default: /* unsupported */
+ socks_request_set_socks5_error(req,
+ SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED);
log_warn(LD_APP,"socks5: unsupported address type %d. Rejecting.",
(int) *(data+3));
return -1;
diff --git a/src/or/circuitstats.c b/src/or/circuitstats.c
index 88a1f9b46c..5336e4046e 100644
--- a/src/or/circuitstats.c
+++ b/src/or/circuitstats.c
@@ -691,7 +691,7 @@ circuit_build_times_get_xm(circuit_build_times_t *cbt)
if (cbt->total_build_times < CBT_NCIRCUITS_TO_OBSERVE)
num_modes = 1;
- nth_max_bin = (build_time_t*)tor_calloc(num_modes, sizeof(build_time_t));
+ nth_max_bin = tor_calloc(num_modes, sizeof(build_time_t));
/* Determine the N most common build times */
for (i = 0; i < nbins; i++) {
@@ -1085,7 +1085,21 @@ circuit_build_times_calculate_timeout(circuit_build_times_t *cbt,
tor_assert(1.0-quantile > 0);
tor_assert(cbt->Xm > 0);
- ret = cbt->Xm/pow(1.0-quantile,1.0/cbt->alpha);
+ /* If either alpha or p are 0, we would divide by zero, yielding an
+ * infinite (double) result; which would be clamped to INT32_MAX.
+ * Instead, initialise ret to INT32_MAX, and skip over these
+ * potentially illegal/trapping divides by zero.
+ */
+ ret = INT32_MAX;
+
+ if (cbt->alpha > 0) {
+ double p;
+ p = pow(1.0-quantile,1.0/cbt->alpha);
+ if (p > 0) {
+ ret = cbt->Xm/p;
+ }
+ }
+
if (ret > INT32_MAX) {
ret = INT32_MAX;
}
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index bd42bd39cb..9ea0023568 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -2070,7 +2070,7 @@ static void
link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ,
crypt_path_t *cpath)
{
- const node_t *exitnode;
+ const node_t *exitnode = NULL;
/* add it into the linked list of streams on this circuit */
log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %u.",
@@ -2104,23 +2104,25 @@ link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ,
circ->isolation_any_streams_attached = 1;
connection_edge_update_circuit_isolation(apconn, circ, 0);
+ /* Compute the exitnode if possible, for logging below */
+ if (cpath->extend_info)
+ exitnode = node_get_by_id(cpath->extend_info->identity_digest);
+
/* See if we can use optimistic data on this circuit */
- if (cpath->extend_info &&
- (exitnode = node_get_by_id(cpath->extend_info->identity_digest)) &&
- exitnode->rs) {
- /* Okay; we know what exit node this is. */
- if (optimistic_data_enabled() &&
- circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL &&
- exitnode->rs->version_supports_optimistic_data)
- apconn->may_use_optimistic_data = 1;
- else
- apconn->may_use_optimistic_data = 0;
- log_info(LD_APP, "Looks like completed circuit to %s %s allow "
- "optimistic data for connection to %s",
- safe_str_client(node_describe(exitnode)),
- apconn->may_use_optimistic_data ? "does" : "doesn't",
- safe_str_client(apconn->socks_request->address));
- }
+ if (optimistic_data_enabled() &&
+ (circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ||
+ circ->base_.purpose == CIRCUIT_PURPOSE_C_REND_JOINED))
+ apconn->may_use_optimistic_data = 1;
+ else
+ apconn->may_use_optimistic_data = 0;
+ log_info(LD_APP, "Looks like completed circuit to %s %s allow "
+ "optimistic data for connection to %s",
+ circ->base_.purpose == CIRCUIT_PURPOSE_C_GENERAL ?
+ /* node_describe() does the right thing if exitnode is NULL */
+ safe_str_client(node_describe(exitnode)) :
+ "hidden service",
+ apconn->may_use_optimistic_data ? "does" : "doesn't",
+ safe_str_client(apconn->socks_request->address));
}
/** Return true iff <b>address</b> is matched by one of the entries in
diff --git a/src/or/config.c b/src/or/config.c
index 85e36c7534..2318e63b8e 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -99,8 +99,6 @@ static config_abbrev_t option_abbrevs_[] = {
{ "PreferTunnelledDirConns", "PreferTunneledDirConns", 0, 0},
{ "BridgeAuthoritativeDirectory", "BridgeAuthoritativeDir", 0, 0},
{ "HashedControlPassword", "__HashedControlSessionPassword", 1, 0},
- { "StrictEntryNodes", "StrictNodes", 0, 1},
- { "StrictExitNodes", "StrictNodes", 0, 1},
{ "VirtualAddrNetwork", "VirtualAddrNetworkIPv4", 0, 0},
{ "_UseFilteringSSLBufferevents", "UseFilteringSSLBufferevents", 0, 1},
{ NULL, NULL, 0, 0},
@@ -127,8 +125,8 @@ static config_abbrev_t option_abbrevs_[] = {
* be chosen first.
*/
static config_var_t option_vars_[] = {
- OBSOLETE("AccountingMaxKB"),
V(AccountingMax, MEMUNIT, "0 bytes"),
+ VAR("AccountingRule", STRING, AccountingRule_option, "max"),
V(AccountingStart, STRING, NULL),
V(Address, STRING, NULL),
V(AllowDotExit, BOOL, "0"),
@@ -196,21 +194,14 @@ static config_var_t option_vars_[] = {
V(CookieAuthFile, STRING, NULL),
V(CountPrivateBandwidth, BOOL, "0"),
V(DataDirectory, FILENAME, NULL),
- OBSOLETE("DebugLogFile"),
V(DisableNetwork, BOOL, "0"),
V(DirAllowPrivateAddresses, BOOL, "0"),
V(TestingAuthDirTimeToLearnReachability, INTERVAL, "30 minutes"),
V(DirListenAddress, LINELIST, NULL),
- OBSOLETE("DirFetchPeriod"),
V(DirPolicy, LINELIST, NULL),
VPORT(DirPort, LINELIST, NULL),
V(DirPortFrontPage, FILENAME, NULL),
- OBSOLETE("DirPostPeriod"),
- OBSOLETE("DirRecordUsageByCountry"),
- OBSOLETE("DirRecordUsageGranularity"),
- OBSOLETE("DirRecordUsageRetainIPs"),
- OBSOLETE("DirRecordUsageSaveInterval"),
- V(DirReqStatistics, BOOL, "1"),
+ VAR("DirReqStatistics", BOOL, DirReqStatistics_option, "1"),
VAR("DirAuthority", LINELIST, DirAuthorities, NULL),
V(DirAuthorityFallbackRate, DOUBLE, "1.0"),
V(DisableAllSwap, BOOL, "0"),
@@ -262,7 +253,6 @@ static config_var_t option_vars_[] = {
V(GeoIPv6File, FILENAME,
SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip6"),
#endif
- OBSOLETE("GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays"),
OBSOLETE("Group"),
V(GuardLifetime, INTERVAL, "0 minutes"),
V(HardwareAccel, BOOL, "0"),
@@ -272,15 +262,11 @@ static config_var_t option_vars_[] = {
V(HashedControlPassword, LINELIST, NULL),
V(HidServDirectoryV2, BOOL, "1"),
VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL),
- OBSOLETE("HiddenServiceExcludeNodes"),
- OBSOLETE("HiddenServiceNodes"),
VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines, NULL),
VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceVersion",LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceAuthorizeClient",LINELIST_S,RendConfigLines, NULL),
V(HidServAuth, LINELIST, NULL),
- OBSOLETE("HSAuthoritativeDir"),
- OBSOLETE("HSAuthorityRecordStats"),
V(CloseHSClientCircuitsImmediatelyOnTimeout, BOOL, "0"),
V(CloseHSServiceRendCircuitsImmediatelyOnTimeout, BOOL, "0"),
V(HTTPProxy, STRING, NULL),
@@ -295,13 +281,9 @@ static config_var_t option_vars_[] = {
V(Socks5Proxy, STRING, NULL),
V(Socks5ProxyUsername, STRING, NULL),
V(Socks5ProxyPassword, STRING, NULL),
- OBSOLETE("IgnoreVersion"),
V(KeepalivePeriod, INTERVAL, "5 minutes"),
VAR("Log", LINELIST, Logs, NULL),
V(LogMessageDomains, BOOL, "0"),
- OBSOLETE("LinkPadding"),
- OBSOLETE("LogLevel"),
- OBSOLETE("LogFile"),
V(LogTimeGranularity, MSEC_INTERVAL, "1 second"),
V(TruncateLogFile, BOOL, "0"),
V(LongLivedPorts, CSV,
@@ -314,7 +296,6 @@ static config_var_t option_vars_[] = {
OBSOLETE("MaxOnionsPending"),
V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"),
V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"),
- OBSOLETE("MonthlyAccountingStart"),
V(MyFamily, STRING, NULL),
V(NewCircuitPeriod, INTERVAL, "30 seconds"),
OBSOLETE("NamingAuthoritativeDirectory"),
@@ -323,7 +304,6 @@ static config_var_t option_vars_[] = {
V(Nickname, STRING, NULL),
V(PredictedPortsRelevanceTime, INTERVAL, "1 hour"),
V(WarnUnsafeSocks, BOOL, "1"),
- OBSOLETE("NoPublish"),
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
V(NumCPUs, UINT, "0"),
V(NumDirectoryGuards, UINT, "0"),
@@ -349,7 +329,6 @@ static config_var_t option_vars_[] = {
V(PathBiasScaleUseThreshold, INT, "-1"),
V(PathsNeededToBuildCircuits, DOUBLE, "-1"),
- OBSOLETE("PathlenCoinWeight"),
V(PerConnBWBurst, MEMUNIT, "0"),
V(PerConnBWRate, MEMUNIT, "0"),
V(PidFile, STRING, NULL),
@@ -369,18 +348,13 @@ static config_var_t option_vars_[] = {
V(RecommendedVersions, LINELIST, NULL),
V(RecommendedClientVersions, LINELIST, NULL),
V(RecommendedServerVersions, LINELIST, NULL),
- OBSOLETE("RedirectExit"),
V(RefuseUnknownExits, AUTOBOOL, "auto"),
V(RejectPlaintextPorts, CSV, ""),
V(RelayBandwidthBurst, MEMUNIT, "0"),
V(RelayBandwidthRate, MEMUNIT, "0"),
- OBSOLETE("RendExcludeNodes"),
- OBSOLETE("RendNodes"),
V(RendPostPeriod, INTERVAL, "1 hour"),
V(RephistTrackTime, INTERVAL, "24 hours"),
- OBSOLETE("RouterFile"),
V(RunAsDaemon, BOOL, "0"),
-// V(RunTesting, BOOL, "0"),
OBSOLETE("RunTesting"), // currently unused
V(Sandbox, BOOL, "0"),
V(SafeLogging, STRING, "1"),
@@ -399,18 +373,16 @@ static config_var_t option_vars_[] = {
VPORT(SocksPort, LINELIST, NULL),
V(SocksTimeout, INTERVAL, "2 minutes"),
V(SSLKeyLifetime, INTERVAL, "0"),
- OBSOLETE("StatusFetchPeriod"),
+ OBSOLETE("StrictEntryNodes"),
+ OBSOLETE("StrictExitNodes"),
V(StrictNodes, BOOL, "0"),
V(Support022HiddenServices, AUTOBOOL, "auto"),
- OBSOLETE("SysLog"),
V(TestSocks, BOOL, "0"),
- OBSOLETE("TestVia"),
V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"),
V(Tor2webMode, BOOL, "0"),
V(TLSECGroup, STRING, NULL),
V(TrackHostExits, CSV, NULL),
V(TrackHostExitsExpire, INTERVAL, "30 minutes"),
- OBSOLETE("TrafficShaping"),
V(TransListenAddress, LINELIST, NULL),
VPORT(TransPort, LINELIST, NULL),
V(TransProxyType, STRING, "default"),
@@ -467,6 +439,7 @@ static config_var_t option_vars_[] = {
V(TestingDescriptorMaxDownloadTries, UINT, "8"),
V(TestingMicrodescMaxDownloadTries, UINT, "8"),
V(TestingCertMaxDownloadTries, UINT, "8"),
+ V(TestingDirAuthVoteExit, ROUTERSET, NULL),
V(TestingDirAuthVoteGuard, ROUTERSET, NULL),
VAR("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, "0"),
@@ -845,7 +818,9 @@ escaped_safe_str(const char *address)
}
/** Add the default directory authorities directly into the trusted dir list,
- * but only add them insofar as they share bits with <b>type</b>. */
+ * but only add them insofar as they share bits with <b>type</b>.
+ * Each authority's bits are restricted to the bits shared with <b>type</b>.
+ * If <b>type</b> is ALL_DIRINFO or NO_DIRINFO (zero), add all authorities. */
static void
add_default_trusted_dir_authorities(dirinfo_type_t type)
{
@@ -865,7 +840,7 @@ add_default_trusted_dir_authorities(dirinfo_type_t type)
"76.73.17.194:9030 F397 038A DC51 3361 35E7 B80B D99C A384 4360 292B",
"gabelmoo orport=443 "
"v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 "
- "212.112.245.170:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281",
+ "131.188.40.189:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281",
"dannenberg orport=443 "
"v3ident=585769C78764D58426B8B52B6651A5A71137189A "
"193.23.244.244:80 7BE6 83E6 5D48 1413 21C5 ED92 F075 C553 64AC 7123",
@@ -987,7 +962,10 @@ consider_adding_dir_servers(const or_options_t *options,
type |= BRIDGE_DIRINFO;
if (!options->AlternateDirAuthority)
type |= V3_DIRINFO | EXTRAINFO_DIRINFO | MICRODESC_DIRINFO;
- add_default_trusted_dir_authorities(type);
+ /* if type == NO_DIRINFO, we don't want to add any of the
+ * default authorities, because we've replaced them all */
+ if (type != NO_DIRINFO)
+ add_default_trusted_dir_authorities(type);
}
if (!options->FallbackDir)
add_default_fallback_dir_servers();
@@ -1432,24 +1410,26 @@ options_act(const or_options_t *old_options)
mark_transport_list();
pt_prepare_proxy_list_for_config_read();
- if (options->ClientTransportPlugin) {
- for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
- if (parse_client_transport_line(options, cl->value, 0)<0) {
- log_warn(LD_BUG,
- "Previously validated ClientTransportPlugin line "
- "could not be added!");
- return -1;
+ if (!options->DisableNetwork) {
+ if (options->ClientTransportPlugin) {
+ for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
+ if (parse_client_transport_line(options, cl->value, 0)<0) {
+ log_warn(LD_BUG,
+ "Previously validated ClientTransportPlugin line "
+ "could not be added!");
+ return -1;
+ }
}
}
- }
- if (options->ServerTransportPlugin && server_mode(options)) {
- for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
- if (parse_server_transport_line(options, cl->value, 0)<0) {
- log_warn(LD_BUG,
- "Previously validated ServerTransportPlugin line "
- "could not be added!");
- return -1;
+ if (options->ServerTransportPlugin && server_mode(options)) {
+ for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
+ if (parse_server_transport_line(options, cl->value, 0)<0) {
+ log_warn(LD_BUG,
+ "Previously validated ServerTransportPlugin line "
+ "could not be added!");
+ return -1;
+ }
}
}
}
@@ -1709,6 +1689,10 @@ options_act(const or_options_t *old_options)
connection_or_update_token_buckets(get_connection_array(), options);
}
+ /* Only collect directory-request statistics on relays and bridges. */
+ options->DirReqStatistics = options->DirReqStatistics_option &&
+ server_mode(options);
+
if (options->CellStatistics || options->DirReqStatistics ||
options->EntryStatistics || options->ExitPortStatistics ||
options->ConnDirectionStatistics ||
@@ -1716,11 +1700,6 @@ options_act(const or_options_t *old_options)
time_t now = time(NULL);
int print_notice = 0;
- /* Only collect directory-request statistics on relays and bridges. */
- if (!server_mode(options)) {
- options->DirReqStatistics = 0;
- }
-
/* Only collect other relay-only statistics on relays. */
if (!public_server_mode(options)) {
options->CellStatistics = 0;
@@ -1739,8 +1718,8 @@ options_act(const or_options_t *old_options)
geoip_dirreq_stats_init(now);
print_notice = 1;
} else {
+ /* disable statistics collection since we have no geoip file */
options->DirReqStatistics = 0;
- /* Don't warn Tor clients, they don't use statistics */
if (options->ORPort_set)
log_notice(LD_CONFIG, "Configured to measure directory request "
"statistics, but no GeoIP database found. "
@@ -2068,6 +2047,13 @@ get_last_resolved_addr(void)
return last_resolved_addr;
}
+/** Reset last_resolved_addr from outside this file. */
+void
+reset_last_resolved_addr(void)
+{
+ last_resolved_addr = 0;
+}
+
/**
* Use <b>options-\>Address</b> to guess our public IP address.
*
@@ -3143,6 +3129,16 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
+ options->AccountingRule = ACCT_MAX;
+ if (options->AccountingRule_option) {
+ if (!strcmp(options->AccountingRule_option, "sum"))
+ options->AccountingRule = ACCT_SUM;
+ else if (!strcmp(options->AccountingRule_option, "max"))
+ options->AccountingRule = ACCT_MAX;
+ else
+ REJECT("AccountingRule must be 'sum' or 'max'");
+ }
+
if (options->HTTPProxy) { /* parse it now */
if (tor_addr_port_lookup(options->HTTPProxy,
&options->HTTPProxyAddr, &options->HTTPProxyPort) < 0)
@@ -3191,11 +3187,11 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
- /* Check if more than one proxy type has been enabled. */
+ /* Check if more than one exclusive proxy type has been enabled. */
if (!!options->Socks4Proxy + !!options->Socks5Proxy +
- !!options->HTTPSProxy + !!options->ClientTransportPlugin > 1)
+ !!options->HTTPSProxy > 1)
REJECT("You have configured more than one proxy type. "
- "(Socks4Proxy|Socks5Proxy|HTTPSProxy|ClientTransportPlugin)");
+ "(Socks4Proxy|Socks5Proxy|HTTPSProxy)");
/* Check if the proxies will give surprising behavior. */
if (options->HTTPProxy && !(options->Socks4Proxy ||
@@ -4850,8 +4846,8 @@ parse_client_transport_line(const or_options_t *options,
if (is_managed) { /* managed */
if (!validate_only && is_useless_proxy) {
- log_notice(LD_GENERAL, "Pluggable transport proxy (%s) does not provide "
- "any needed transports and will not be launched.", line);
+ log_info(LD_GENERAL, "Pluggable transport proxy (%s) does not provide "
+ "any needed transports and will not be launched.", line);
}
/* If we are not just validating, use the rest of the line as the
@@ -4872,6 +4868,13 @@ parse_client_transport_line(const or_options_t *options,
pt_kickstart_client_proxy(transport_list, proxy_argv);
}
} else { /* external */
+ /* ClientTransportPlugins connecting through a proxy is managed only. */
+ if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
+ log_warn(LD_CONFIG, "You have configured an external proxy with another "
+ "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy)");
+ goto err;
+ }
+
if (smartlist_len(transport_list) != 1) {
log_warn(LD_CONFIG, "You can't have an external proxy with "
"more than one transports.");
@@ -5198,8 +5201,9 @@ parse_server_transport_line(const or_options_t *options,
/** Read the contents of a DirAuthority line from <b>line</b>. If
* <b>validate_only</b> is 0, and the line is well-formed, and it
* shares any bits with <b>required_type</b> or <b>required_type</b>
- * is 0, then add the dirserver described in the line (minus whatever
- * bits it's missing) as a valid authority. Return 0 on success,
+ * is NO_DIRINFO (zero), then add the dirserver described in the line
+ * (minus whatever bits it's missing) as a valid authority.
+ * Return 0 on success or filtering out by type,
* or -1 if the line isn't well-formed or if we can't add it. */
static int
parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
diff --git a/src/or/config.h b/src/or/config.h
index 8a1919c2ed..fd95698144 100644
--- a/src/or/config.h
+++ b/src/or/config.h
@@ -29,6 +29,7 @@ setopt_err_t options_trial_assign(config_line_t *list, int use_defaults,
int clear_first, char **msg);
uint32_t get_last_resolved_addr(void);
+void reset_last_resolved_addr(void);
int resolve_my_address(int warn_severity, const or_options_t *options,
uint32_t *addr_out,
const char **method_out, char **hostname_out);
diff --git a/src/or/connection.c b/src/or/connection.c
index 26ee4faf20..5c1b6d9bba 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -1688,14 +1688,14 @@ get_proxy_type(void)
{
const or_options_t *options = get_options();
- if (options->HTTPSProxy)
+ if (options->ClientTransportPlugin)
+ return PROXY_PLUGGABLE;
+ else if (options->HTTPSProxy)
return PROXY_CONNECT;
else if (options->Socks4Proxy)
return PROXY_SOCKS4;
else if (options->Socks5Proxy)
return PROXY_SOCKS5;
- else if (options->ClientTransportPlugin)
- return PROXY_PLUGGABLE;
else
return PROXY_NONE;
}
@@ -4386,6 +4386,8 @@ client_check_address_changed(tor_socket_t sock)
SMARTLIST_FOREACH(outgoing_addrs, tor_addr_t*, a_ptr, tor_free(a_ptr));
smartlist_clear(outgoing_addrs);
smartlist_add(outgoing_addrs, tor_memdup(&out_addr, sizeof(tor_addr_t)));
+ /* We'll need to resolve ourselves again. */
+ reset_last_resolved_addr();
/* Okay, now change our keys. */
ip_address_changed(1);
}
@@ -4787,6 +4789,27 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
{
const or_options_t *options = get_options();
+ /* Client Transport Plugins can use another proxy, but that should be hidden
+ * from the rest of tor (as the plugin is responsible for dealing with the
+ * proxy), check it first, then check the rest of the proxy types to allow
+ * the config to have unused ClientTransportPlugin entries.
+ */
+ if (options->ClientTransportPlugin) {
+ const transport_t *transport = NULL;
+ int r;
+ r = get_transport_by_bridge_addrport(&conn->addr, conn->port, &transport);
+ if (r<0)
+ return -1;
+ if (transport) { /* transport found */
+ tor_addr_copy(addr, &transport->addr);
+ *port = transport->port;
+ *proxy_type = transport->socks_version;
+ return 0;
+ }
+
+ /* Unused ClientTransportPlugin. */
+ }
+
if (options->HTTPSProxy) {
tor_addr_copy(addr, &options->HTTPSProxyAddr);
*port = options->HTTPSProxyPort;
@@ -4802,19 +4825,6 @@ get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
*port = options->Socks5ProxyPort;
*proxy_type = PROXY_SOCKS5;
return 0;
- } else if (options->ClientTransportPlugin ||
- options->Bridges) {
- const transport_t *transport = NULL;
- int r;
- r = get_transport_by_bridge_addrport(&conn->addr, conn->port, &transport);
- if (r<0)
- return -1;
- if (transport) { /* transport found */
- tor_addr_copy(addr, &transport->addr);
- *port = transport->port;
- *proxy_type = transport->socks_version;
- return 0;
- }
}
tor_addr_make_unspec(addr);
@@ -4838,7 +4848,7 @@ log_failed_proxy_connection(connection_t *conn)
log_warn(LD_NET,
"The connection to the %s proxy server at %s just failed. "
"Make sure that the proxy server is up and running.",
- proxy_type_to_string(get_proxy_type()),
+ proxy_type_to_string(proxy_type),
fmt_addrport(&proxy_addr, proxy_port));
}
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 49f9ba4978..522807d7ba 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -1767,7 +1767,8 @@ connection_ap_supports_optimistic_data(const entry_connection_t *conn)
general circuit. */
if (edge_conn->on_circuit == NULL ||
edge_conn->on_circuit->state != CIRCUIT_STATE_OPEN ||
- edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL)
+ (edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL &&
+ edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_REND_JOINED))
return 0;
return conn->may_use_optimistic_data;
@@ -2764,7 +2765,6 @@ connection_exit_connect(edge_connection_t *edge_conn)
/* also, deliver a 'connected' cell back through the circuit. */
if (connection_edge_is_rendezvous_stream(edge_conn)) {
- /* rendezvous stream */
/* don't send an address back! */
connection_edge_send_command(edge_conn,
RELAY_COMMAND_CONNECTED,
diff --git a/src/or/control.c b/src/or/control.c
index 60aa869439..92dd2309ed 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -47,6 +47,7 @@
#include <sys/resource.h>
#endif
+#include "crypto_s2k.h"
#include "procmon.h"
/** Yield true iff <b>s</b> is the state of a control_connection_t that has
@@ -949,7 +950,7 @@ static int
handle_control_setevents(control_connection_t *conn, uint32_t len,
const char *body)
{
- int event_code = -1;
+ int event_code;
event_mask_t event_mask = 0;
smartlist_t *events = smartlist_new();
@@ -963,6 +964,8 @@ handle_control_setevents(control_connection_t *conn, uint32_t len,
continue;
} else {
int i;
+ event_code = -1;
+
for (i = 0; control_event_table[i].event_name != NULL; ++i) {
if (!strcasecmp(ev, control_event_table[i].event_name)) {
event_code = control_event_table[i].event_code;
@@ -993,7 +996,8 @@ handle_control_setevents(control_connection_t *conn, uint32_t len,
/** Decode the hashed, base64'd passwords stored in <b>passwords</b>.
* Return a smartlist of acceptable passwords (unterminated strings of
- * length S2K_SPECIFIER_LEN+DIGEST_LEN) on success, or NULL on failure.
+ * length S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN) on success, or NULL on
+ * failure.
*/
smartlist_t *
decode_hashed_passwords(config_line_t *passwords)
@@ -1009,16 +1013,17 @@ decode_hashed_passwords(config_line_t *passwords)
if (!strcmpstart(hashed, "16:")) {
if (base16_decode(decoded, sizeof(decoded), hashed+3, strlen(hashed+3))<0
- || strlen(hashed+3) != (S2K_SPECIFIER_LEN+DIGEST_LEN)*2) {
+ || strlen(hashed+3) != (S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN)*2) {
goto err;
}
} else {
if (base64_decode(decoded, sizeof(decoded), hashed, strlen(hashed))
- != S2K_SPECIFIER_LEN+DIGEST_LEN) {
+ != S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN) {
goto err;
}
}
- smartlist_add(sl, tor_memdup(decoded, S2K_SPECIFIER_LEN+DIGEST_LEN));
+ smartlist_add(sl,
+ tor_memdup(decoded, S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN));
}
return sl;
@@ -1168,15 +1173,19 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
bad_password = 1;
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
smartlist_free(sl);
+ sl = NULL;
} else {
SMARTLIST_FOREACH(sl, char *, expected,
{
- secret_to_key(received,DIGEST_LEN,password,password_len,expected);
- if (tor_memeq(expected+S2K_SPECIFIER_LEN, received, DIGEST_LEN))
+ secret_to_key_rfc2440(received,DIGEST_LEN,
+ password,password_len,expected);
+ if (tor_memeq(expected + S2K_RFC2440_SPECIFIER_LEN,
+ received, DIGEST_LEN))
goto ok;
});
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
smartlist_free(sl);
+ sl = NULL;
if (used_quoted_string)
errstr = "Password did not match HashedControlPassword value from "
diff --git a/src/or/directory.c b/src/or/directory.c
index 1aaa75ccee..f06b715fd2 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -452,7 +452,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
return;
if (!get_via_tor) {
- if (options->UseBridges && type != BRIDGE_DIRINFO) {
+ if (options->UseBridges && !(type & BRIDGE_DIRINFO)) {
/* We want to ask a running bridge for which we have a descriptor.
*
* When we ask choose_random_entry() for a bridge, we specify what
@@ -479,7 +479,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
"nodes are available yet.");
return;
} else {
- if (prefer_authority || type == BRIDGE_DIRINFO) {
+ if (prefer_authority || (type & BRIDGE_DIRINFO)) {
/* only ask authdirservers, and don't ask myself */
rs = router_pick_trusteddirserver(type, pds_flags);
if (rs == NULL && (pds_flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
@@ -506,7 +506,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
return;
}
}
- if (!rs && type != BRIDGE_DIRINFO) {
+ if (!rs && !(type & BRIDGE_DIRINFO)) {
/* */
rs = directory_pick_generic_dirserver(type, pds_flags,
dir_purpose);
@@ -523,12 +523,12 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
/* anybody with a non-zero dirport will do. Disregard firewalls. */
pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
rs = router_pick_directory_server(type, pds_flags);
- /* If we have any hope of building an indirect conn, we know some router
- * descriptors. If (rs==NULL), we can't build circuits anyway, so
- * there's no point in falling back to the authorities in this case. */
}
}
+ /* If we have any hope of building an indirect conn, we know some router
+ * descriptors. If (rs==NULL), we can't build circuits anyway, so
+ * there's no point in falling back to the authorities in this case. */
if (rs) {
const dir_indirection_t indirection =
get_via_tor ? DIRIND_ANONYMOUS : DIRIND_ONEHOP;
@@ -3442,6 +3442,9 @@ download_status_increment_failure(download_status_t *dls, int status_code,
void
download_status_reset(download_status_t *dls)
{
+ if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD)
+ return; /* Don't reset this. */
+
const smartlist_t *schedule = find_dl_schedule_and_len(
dls, get_options()->DirPort_set);
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index a5ad742b96..5a41247aa0 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -478,7 +478,7 @@ dirserv_add_multiple_descriptors(const char *desc, uint8_t purpose,
s = desc;
list = smartlist_new();
if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 0, 0,
- annotation_buf)) {
+ annotation_buf, NULL)) {
SMARTLIST_FOREACH(list, routerinfo_t *, ri, {
msg_out = NULL;
tor_assert(ri->purpose == purpose);
@@ -494,7 +494,7 @@ dirserv_add_multiple_descriptors(const char *desc, uint8_t purpose,
s = desc;
if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 1, 0,
- NULL)) {
+ NULL, NULL)) {
SMARTLIST_FOREACH(list, extrainfo_t *, ei, {
msg_out = NULL;
@@ -664,7 +664,7 @@ directory_remove_invalid(void)
smartlist_add_all(nodes, nodelist_get_list());
SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) {
- const char *msg;
+ const char *msg = NULL;
routerinfo_t *ent = node->ri;
char description[NODE_DESC_BUF_LEN];
uint32_t r;
@@ -1395,6 +1395,8 @@ dirserv_compute_performance_thresholds(routerlist_t *rl,
routerinfo_t *ri = node->ri;
const char *id = node->identity;
uint32_t bw_kb;
+ /* resolve spurious clang shallow analysis null pointer errors */
+ tor_assert(ri);
node->is_exit = (!router_exit_policy_rejects_all(ri) &&
exit_policy_is_general_exit(ri->exit_policy));
uptimes[n_active] = (uint32_t)real_uptime(ri, now);
@@ -2026,75 +2028,6 @@ get_possible_sybil_list(const smartlist_t *routers)
return omit_as_sybil;
}
-/** Return non-zero iff a relay running the Tor version specified in
- * <b>platform</b> is suitable for use as a potential entry guard. */
-static int
-is_router_version_good_for_possible_guard(const char *platform)
-{
- static int parsed_versions_initialized = 0;
- static tor_version_t first_good_0_2_1_guard_version;
- static tor_version_t first_good_0_2_2_guard_version;
- static tor_version_t first_good_later_guard_version;
-
- tor_version_t router_version;
-
- /* XXX024 This block should be extracted into its own function. */
- /* XXXX Begin code copied from tor_version_as_new_as (in routerparse.c) */
- {
- char *s, *s2, *start;
- char tmp[128];
-
- tor_assert(platform);
-
- /* nonstandard Tor; be safe and say yes */
- if (strcmpstart(platform,"Tor "))
- return 1;
-
- start = (char *)eat_whitespace(platform+3);
- if (!*start) return 0;
- s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
- s2 = (char*)eat_whitespace(s);
- if (!strcmpstart(s2, "(r") || !strcmpstart(s2, "(git-"))
- s = (char*)find_whitespace(s2);
-
- if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
- return 0;
- strlcpy(tmp, start, s-start+1);
-
- if (tor_version_parse(tmp, &router_version)<0) {
- log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
- return 1; /* be safe and say yes */
- }
- }
- /* XXXX End code copied from tor_version_as_new_as (in routerparse.c) */
-
- if (!parsed_versions_initialized) {
- /* CVE-2011-2769 was fixed on the relay side in Tor versions
- * 0.2.1.31, 0.2.2.34, and 0.2.3.6-alpha. */
- tor_assert(tor_version_parse("0.2.1.31",
- &first_good_0_2_1_guard_version)>=0);
- tor_assert(tor_version_parse("0.2.2.34",
- &first_good_0_2_2_guard_version)>=0);
- tor_assert(tor_version_parse("0.2.3.6-alpha",
- &first_good_later_guard_version)>=0);
-
- /* Don't parse these constant version strings once for every relay
- * for every vote. */
- parsed_versions_initialized = 1;
- }
-
- return ((tor_version_same_series(&first_good_0_2_1_guard_version,
- &router_version) &&
- tor_version_compare(&first_good_0_2_1_guard_version,
- &router_version) <= 0) ||
- (tor_version_same_series(&first_good_0_2_2_guard_version,
- &router_version) &&
- tor_version_compare(&first_good_0_2_2_guard_version,
- &router_version) <= 0) ||
- (tor_version_compare(&first_good_later_guard_version,
- &router_version) <= 0));
-}
-
/** Extract status information from <b>ri</b> and from other authority
* functions and store it in <b>rs</b>>.
*
@@ -2133,8 +2066,7 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
((options->AuthDirGuardBWGuarantee &&
routerbw_kb >= options->AuthDirGuardBWGuarantee/1000) ||
routerbw_kb >= MIN(guard_bandwidth_including_exits_kb,
- guard_bandwidth_excluding_exits_kb)) &&
- is_router_version_good_for_possible_guard(ri->platform)) {
+ guard_bandwidth_excluding_exits_kb))) {
long tk = rep_hist_get_weighted_time_known(
node->identity, now);
double wfu = rep_hist_get_weighted_fractional_uptime(
@@ -2167,12 +2099,19 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
rs->ipv6_orport = ri->ipv6_orport;
}
- /* Iff we are in a testing network, use TestingDirAuthVoteGuard to
+ /* Iff we are in a testing network, use TestingDirAuthVoteExit to
+ give out Exit flags, and TestingDirAuthVoteGuard to
give out Guard flags. */
- if (options->TestingTorNetwork &&
- routerset_contains_routerstatus(options->TestingDirAuthVoteGuard,
+ if (options->TestingTorNetwork) {
+ if (routerset_contains_routerstatus(options->TestingDirAuthVoteExit,
+ rs, 0)) {
+ rs->is_exit = 1;
+ }
+
+ if (routerset_contains_routerstatus(options->TestingDirAuthVoteGuard,
rs, 0)) {
- rs->is_possible_guard = 1;
+ rs->is_possible_guard = 1;
+ }
}
}
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 9ad92ca116..66374623ad 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -647,6 +647,8 @@ dirvote_compute_params(smartlist_t *votes, int method, int total_authorities)
next_param = NULL;
else
next_param = smartlist_get(param_list, param_sl_idx+1);
+ /* resolve spurious clang shallow analysis null pointer errors */
+ tor_assert(param);
if (!next_param || strncmp(next_param, param, cur_param_len)) {
/* We've reached the end of a series. */
/* Make sure enough authorities voted on this param, unless the
@@ -3286,8 +3288,8 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
{
smartlist_t *lst = microdescs_parse_from_string(output,
- output+strlen(output), 0,
- SAVED_NOWHERE);
+ output+strlen(output), 0,
+ SAVED_NOWHERE, NULL);
if (smartlist_len(lst) != 1) {
log_warn(LD_DIR, "We generated a microdescriptor we couldn't parse.");
SMARTLIST_FOREACH(lst, microdesc_t *, md, microdesc_free(md));
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index b95391e37a..b160235289 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1003,7 +1003,8 @@ node_understands_microdescriptors(const node_t *node)
}
/** Return true iff <b>node</b> is able to answer directory questions
- * of type <b>dirinfo</b>. */
+ * of type <b>dirinfo</b>. Always returns true if <b>dirinfo</b> is
+ * NO_DIRINFO (zero). */
static int
node_can_handle_dirinfo(const node_t *node, dirinfo_type_t dirinfo)
{
@@ -1025,13 +1026,13 @@ node_can_handle_dirinfo(const node_t *node, dirinfo_type_t dirinfo)
* <b>state</b> is non-NULL, this is for a specific circuit --
* make sure not to pick this circuit's exit or any node in the
* exit's family. If <b>state</b> is NULL, we're looking for a random
- * guard (likely a bridge). If <b>dirinfo</b> is not NO_DIRINFO, then
- * only select from nodes that know how to answer directory questions
+ * guard (likely a bridge). If <b>dirinfo</b> is not NO_DIRINFO (zero),
+ * then only select from nodes that know how to answer directory questions
* of that type. */
const node_t *
choose_random_entry(cpath_build_state_t *state)
{
- return choose_random_entry_impl(state, 0, 0, NULL);
+ return choose_random_entry_impl(state, 0, NO_DIRINFO, NULL);
}
/** Pick a live (up and listed) directory guard from entry_guards for
@@ -1139,7 +1140,9 @@ populate_live_entry_guards(smartlist_t *live_entry_guards,
* If <b>for_directory</b> is set, we are looking for a directory guard.
*
* <b>dirinfo_type</b> contains the kind of directory information we
- * are looking for in our node.
+ * are looking for in our node, or NO_DIRINFO (zero) if we are not
+ * looking for any particular directory information (when set to
+ * NO_DIRINFO, the <b>dirinfo_type</b> filter is ignored).
*
* If <b>n_options_out</b> is set, we set it to the number of
* candidate guard nodes we had before picking a specific guard node.
@@ -2291,6 +2294,13 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
node = node_get_mutable_by_id(ri->cache_info.identity_digest);
tor_assert(node);
rewrite_node_address_for_bridge(bridge, node);
+ if (tor_digest_is_zero(bridge->identity)) {
+ memcpy(bridge->identity,ri->cache_info.identity_digest, DIGEST_LEN);
+ log_notice(LD_DIR, "Learned identity %s for bridge at %s:%d",
+ hex_str(bridge->identity, DIGEST_LEN),
+ fmt_and_decorate_addr(&bridge->addr),
+ (int) bridge->port);
+ }
add_an_entry_guard(node, 1, 1, 0, 0);
log_notice(LD_DIR, "new bridge descriptor '%s' (%s): %s", ri->nickname,
diff --git a/src/or/hibernate.c b/src/or/hibernate.c
index c433ac1be9..b3761cfabf 100644
--- a/src/or/hibernate.c
+++ b/src/or/hibernate.c
@@ -410,6 +410,17 @@ configure_accounting(time_t now)
accounting_set_wakeup_time();
}
+/** Return the relevant number of bytes sent/received this interval
+ * based on the set AccountingRule */
+static uint64_t
+get_accounting_bytes(void)
+{
+ if (get_options()->AccountingRule == ACCT_SUM)
+ return n_bytes_read_in_interval+n_bytes_written_in_interval;
+ else
+ return MAX(n_bytes_read_in_interval, n_bytes_written_in_interval);
+}
+
/** Set expected_bandwidth_usage based on how much we sent/received
* per minute last interval (if we were up for at least 30 minutes),
* or based on our declared bandwidth otherwise. */
@@ -421,6 +432,11 @@ update_expected_bandwidth(void)
uint64_t max_configured = (options->RelayBandwidthRate > 0 ?
options->RelayBandwidthRate :
options->BandwidthRate) * 60;
+ /* max_configured is the larger of bytes read and bytes written
+ * If we are accounting based on sum, worst case is both are
+ * at max, doubling the expected sum of bandwidth */
+ if (get_options()->AccountingRule == ACCT_SUM)
+ max_configured *= 2;
#define MIN_TIME_FOR_MEASUREMENT (1800)
@@ -439,8 +455,7 @@ update_expected_bandwidth(void)
* doesn't know to store soft-limit info. Just take rate at which
* we were reading/writing in the last interval as our expected rate.
*/
- uint64_t used = MAX(n_bytes_written_in_interval,
- n_bytes_read_in_interval);
+ uint64_t used = get_accounting_bytes();
expected = used / (n_seconds_active_in_interval / 60);
} else {
/* If we haven't gotten enough data last interval, set 'expected'
@@ -715,8 +730,7 @@ hibernate_hard_limit_reached(void)
uint64_t hard_limit = get_options()->AccountingMax;
if (!hard_limit)
return 0;
- return n_bytes_read_in_interval >= hard_limit
- || n_bytes_written_in_interval >= hard_limit;
+ return get_accounting_bytes() >= hard_limit;
}
/** Return true iff we have sent/received almost all the bytes we are willing
@@ -747,8 +761,7 @@ hibernate_soft_limit_reached(void)
if (!soft_limit)
return 0;
- return n_bytes_read_in_interval >= soft_limit
- || n_bytes_written_in_interval >= soft_limit;
+ return get_accounting_bytes() >= soft_limit;
}
/** Called when we get a SIGINT, or when bandwidth soft limit is
@@ -772,8 +785,7 @@ hibernate_begin(hibernate_state_t new_state, time_t now)
hibernate_state == HIBERNATE_STATE_LIVE) {
soft_limit_hit_at = now;
n_seconds_to_hit_soft_limit = n_seconds_active_in_interval;
- n_bytes_at_soft_limit = MAX(n_bytes_read_in_interval,
- n_bytes_written_in_interval);
+ n_bytes_at_soft_limit = get_accounting_bytes();
}
/* close listeners. leave control listener(s). */
@@ -1003,13 +1015,22 @@ getinfo_helper_accounting(control_connection_t *conn,
U64_PRINTF_ARG(n_bytes_written_in_interval));
} else if (!strcmp(question, "accounting/bytes-left")) {
uint64_t limit = get_options()->AccountingMax;
- uint64_t read_left = 0, write_left = 0;
- if (n_bytes_read_in_interval < limit)
- read_left = limit - n_bytes_read_in_interval;
- if (n_bytes_written_in_interval < limit)
- write_left = limit - n_bytes_written_in_interval;
- tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
- U64_PRINTF_ARG(read_left), U64_PRINTF_ARG(write_left));
+ if (get_options()->AccountingRule == ACCT_SUM) {
+ uint64_t total_left = 0;
+ uint64_t total_bytes = get_accounting_bytes();
+ if (total_bytes < limit)
+ total_left = limit - total_bytes;
+ tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
+ U64_PRINTF_ARG(total_left), U64_PRINTF_ARG(total_left));
+ } else {
+ uint64_t read_left = 0, write_left = 0;
+ if (n_bytes_read_in_interval < limit)
+ read_left = limit - n_bytes_read_in_interval;
+ if (n_bytes_written_in_interval < limit)
+ write_left = limit - n_bytes_written_in_interval;
+ tor_asprintf(answer, U64_FORMAT" "U64_FORMAT,
+ U64_PRINTF_ARG(read_left), U64_PRINTF_ARG(write_left));
+ }
} else if (!strcmp(question, "accounting/interval-start")) {
*answer = tor_malloc(ISO_TIME_LEN+1);
format_iso_time(*answer, interval_start_time);
diff --git a/src/or/hibernate.h b/src/or/hibernate.h
index 38ecb75129..799b582543 100644
--- a/src/or/hibernate.h
+++ b/src/or/hibernate.h
@@ -28,6 +28,7 @@ void consider_hibernation(time_t now);
int getinfo_helper_accounting(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
+uint64_t get_accounting_max_total(void);
#ifdef HIBERNATE_PRIVATE
/** Possible values of hibernate_state */
diff --git a/src/or/main.c b/src/or/main.c
index ffbed6edbe..1d26223eb6 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -28,6 +28,7 @@
#include "connection_or.h"
#include "control.h"
#include "cpuworker.h"
+#include "crypto_s2k.h"
#include "directory.h"
#include "dirserv.h"
#include "dirvote.h"
@@ -2674,11 +2675,11 @@ do_hash_password(void)
{
char output[256];
- char key[S2K_SPECIFIER_LEN+DIGEST_LEN];
+ char key[S2K_RFC2440_SPECIFIER_LEN+DIGEST_LEN];
- crypto_rand(key, S2K_SPECIFIER_LEN-1);
- key[S2K_SPECIFIER_LEN-1] = (uint8_t)96; /* Hash 64 K of data. */
- secret_to_key(key+S2K_SPECIFIER_LEN, DIGEST_LEN,
+ crypto_rand(key, S2K_RFC2440_SPECIFIER_LEN-1);
+ key[S2K_RFC2440_SPECIFIER_LEN-1] = (uint8_t)96; /* Hash 64 K of data. */
+ secret_to_key_rfc2440(key+S2K_RFC2440_SPECIFIER_LEN, DIGEST_LEN,
get_options()->command_arg, strlen(get_options()->command_arg),
key);
base16_encode(output, sizeof(output), key, sizeof(key));
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index 576fed0066..14faa2e10c 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -147,12 +147,17 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
int no_save, time_t listed_at,
smartlist_t *requested_digests256)
{
+ void * const DIGEST_REQUESTED = (void*)1;
+ void * const DIGEST_RECEIVED = (void*)2;
+ void * const DIGEST_INVALID = (void*)3;
+
smartlist_t *descriptors, *added;
const int allow_annotations = (where != SAVED_NOWHERE);
+ smartlist_t *invalid_digests = smartlist_new();
descriptors = microdescs_parse_from_string(s, eos,
allow_annotations,
- where);
+ where, invalid_digests);
if (listed_at != (time_t)-1) {
SMARTLIST_FOREACH(descriptors, microdesc_t *, md,
md->last_listed = listed_at);
@@ -161,19 +166,38 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
digestmap_t *requested; /* XXXX actually we should just use a
digest256map */
requested = digestmap_new();
+ /* Set requested[d] to DIGEST_REQUESTED for every md we requested. */
SMARTLIST_FOREACH(requested_digests256, const char *, cp,
- digestmap_set(requested, cp, (void*)1));
+ digestmap_set(requested, cp, DIGEST_REQUESTED));
+ /* Set requested[d] to DIGEST_INVALID for every md we requested which we
+ * will never be able to parse. Remove the ones we didn't request from
+ * invalid_digests.
+ */
+ SMARTLIST_FOREACH_BEGIN(invalid_digests, char *, cp) {
+ if (digestmap_get(requested, cp)) {
+ digestmap_set(requested, cp, DIGEST_INVALID);
+ } else {
+ tor_free(cp);
+ SMARTLIST_DEL_CURRENT(invalid_digests, cp);
+ }
+ } SMARTLIST_FOREACH_END(cp);
+ /* Update requested[d] to 2 for the mds we asked for and got. Delete the
+ * ones we never requested from the 'descriptors' smartlist.
+ */
SMARTLIST_FOREACH_BEGIN(descriptors, microdesc_t *, md) {
if (digestmap_get(requested, md->digest)) {
- digestmap_set(requested, md->digest, (void*)2);
+ digestmap_set(requested, md->digest, DIGEST_RECEIVED);
} else {
log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Received non-requested microdesc");
microdesc_free(md);
SMARTLIST_DEL_CURRENT(descriptors, md);
}
} SMARTLIST_FOREACH_END(md);
+ /* Remove the ones we got or the invalid ones from requested_digests256.
+ */
SMARTLIST_FOREACH_BEGIN(requested_digests256, char *, cp) {
- if (digestmap_get(requested, cp) == (void*)2) {
+ void *status = digestmap_get(requested, cp);
+ if (status == DIGEST_RECEIVED || status == DIGEST_INVALID) {
tor_free(cp);
SMARTLIST_DEL_CURRENT(requested_digests256, cp);
}
@@ -181,6 +205,24 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
digestmap_free(requested, NULL);
}
+ /* For every requested microdescriptor that was unparseable, mark it
+ * as not to be retried. */
+ if (smartlist_len(invalid_digests)) {
+ networkstatus_t *ns =
+ networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
+ if (ns) {
+ SMARTLIST_FOREACH_BEGIN(invalid_digests, char *, d) {
+ routerstatus_t *rs =
+ router_get_mutable_consensus_status_by_descriptor_digest(ns, d);
+ if (rs && tor_memeq(d, rs->descriptor_digest, DIGEST256_LEN)) {
+ download_status_mark_impossible(&rs->dl_status);
+ }
+ } SMARTLIST_FOREACH_END(d);
+ }
+ }
+ SMARTLIST_FOREACH(invalid_digests, uint8_t *, d, tor_free(d));
+ smartlist_free(invalid_digests);
+
added = microdescs_add_list_to_cache(cache, descriptors, where, no_save);
smartlist_free(descriptors);
return added;
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 95eb32035b..565f3cb1eb 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -83,7 +83,11 @@ static consensus_waiting_for_certs_t
* before the current consensus becomes invalid. */
static time_t time_to_download_next_consensus[N_CONSENSUS_FLAVORS];
/** Download status for the current consensus networkstatus. */
-static download_status_t consensus_dl_status[N_CONSENSUS_FLAVORS];
+static download_status_t consensus_dl_status[N_CONSENSUS_FLAVORS] =
+ {
+ { 0, 0, DL_SCHED_CONSENSUS },
+ { 0, 0, DL_SCHED_CONSENSUS },
+ };
/** True iff we have logged a warning about this OR's version being older than
* listed by the authorities. */
@@ -591,10 +595,10 @@ networkstatus_vote_find_entry_idx(networkstatus_t *ns,
/** As router_get_consensus_status_by_descriptor_digest, but does not return
* a const pointer. */
-routerstatus_t *
-router_get_mutable_consensus_status_by_descriptor_digest(
+MOCK_IMPL(routerstatus_t *,
+router_get_mutable_consensus_status_by_descriptor_digest,(
networkstatus_t *consensus,
- const char *digest)
+ const char *digest))
{
if (!consensus)
consensus = current_consensus;
@@ -624,8 +628,8 @@ router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus,
/** Given the digest of a router descriptor, return its current download
* status, or NULL if the digest is unrecognized. */
-download_status_t *
-router_get_dl_status_by_descriptor_digest(const char *d)
+MOCK_IMPL(download_status_t *,
+router_get_dl_status_by_descriptor_digest,(const char *d))
{
routerstatus_t *rs;
if (!current_ns_consensus)
@@ -754,6 +758,9 @@ update_consensus_networkstatus_downloads(time_t now)
resource = networkstatus_get_flavor_name(i);
+ /* Let's make sure we remembered to update consensus_dl_status */
+ tor_assert(consensus_dl_status[i].schedule == DL_SCHED_CONSENSUS);
+
if (!download_status_is_ready(&consensus_dl_status[i], now,
options->TestingConsensusMaxDownloadTries))
continue; /* We failed downloading a consensus too recently. */
@@ -988,8 +995,8 @@ networkstatus_get_latest_consensus(void)
/** Return the latest consensus we have whose flavor matches <b>f</b>, or NULL
* if we don't have one. */
-networkstatus_t *
-networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
+MOCK_IMPL(networkstatus_t *,
+networkstatus_get_latest_consensus_by_flavor,(consensus_flavor_t f))
{
if (f == FLAV_NS)
return current_ns_consensus;
@@ -1116,7 +1123,7 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c,
rs_new->last_dir_503_at = rs_old->last_dir_503_at;
if (tor_memeq(rs_old->descriptor_digest, rs_new->descriptor_digest,
- DIGEST_LEN)) {
+ DIGEST_LEN)) { /* XXXX Change this to digest256_len */
/* And the same descriptor too! */
memcpy(&rs_new->dl_status, &rs_old->dl_status,sizeof(download_status_t));
}
@@ -1671,17 +1678,22 @@ networkstatus_dump_bridge_status_to_file(time_t now)
char *status = networkstatus_getinfo_by_purpose("bridge", now);
const or_options_t *options = get_options();
char *fname = NULL;
- char *thresholds = NULL, *thresholds_and_status = NULL;
+ char *thresholds = NULL;
+ char *published_thresholds_and_status = NULL;
routerlist_t *rl = router_get_routerlist();
+ char published[ISO_TIME_LEN+1];
+
+ format_iso_time(published, now);
dirserv_compute_bridge_flag_thresholds(rl);
thresholds = dirserv_get_flag_thresholds_line();
- tor_asprintf(&thresholds_and_status, "flag-thresholds %s\n%s",
- thresholds, status);
+ tor_asprintf(&published_thresholds_and_status,
+ "published %s\nflag-thresholds %s\n%s",
+ published, thresholds, status);
tor_asprintf(&fname, "%s"PATH_SEPARATOR"networkstatus-bridges",
options->DataDirectory);
- write_str_to_file(fname,thresholds_and_status,0);
+ write_str_to_file(fname,published_thresholds_and_status,0);
tor_free(thresholds);
- tor_free(thresholds_and_status);
+ tor_free(published_thresholds_and_status);
tor_free(fname);
tor_free(status);
}
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index be0a86cdd8..344e4de72e 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -12,6 +12,8 @@
#ifndef TOR_NETWORKSTATUS_H
#define TOR_NETWORKSTATUS_H
+#include "testsupport.h"
+
void networkstatus_reset_warnings(void);
void networkstatus_reset_download_failures(void);
int router_reload_consensus_networkstatus(void);
@@ -35,16 +37,19 @@ routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
const char *digest);
int networkstatus_vote_find_entry_idx(networkstatus_t *ns,
const char *digest, int *found_out);
-download_status_t *router_get_dl_status_by_descriptor_digest(const char *d);
+
+MOCK_DECL(download_status_t *,router_get_dl_status_by_descriptor_digest,
+ (const char *d));
+
const routerstatus_t *router_get_consensus_status_by_id(const char *digest);
routerstatus_t *router_get_mutable_consensus_status_by_id(
const char *digest);
const routerstatus_t *router_get_consensus_status_by_descriptor_digest(
networkstatus_t *consensus,
const char *digest);
-routerstatus_t *router_get_mutable_consensus_status_by_descriptor_digest(
- networkstatus_t *consensus,
- const char *digest);
+MOCK_DECL(routerstatus_t *,
+ router_get_mutable_consensus_status_by_descriptor_digest,
+ (networkstatus_t *consensus, const char *digest));
const routerstatus_t *router_get_consensus_status_by_nickname(
const char *nickname,
int warn_if_unnamed);
@@ -60,8 +65,8 @@ int consensus_is_waiting_for_certs(void);
int client_would_use_router(const routerstatus_t *rs, time_t now,
const or_options_t *options);
networkstatus_t *networkstatus_get_latest_consensus(void);
-networkstatus_t *networkstatus_get_latest_consensus_by_flavor(
- consensus_flavor_t f);
+MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus_by_flavor,
+ (consensus_flavor_t f));
networkstatus_t *networkstatus_get_live_consensus(time_t now);
networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now,
int flavor);
diff --git a/src/or/or.h b/src/or/or.h
index 06d4e3c926..3adec7a961 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -14,7 +14,7 @@
#include "orconfig.h"
-#ifdef __COVERITY__
+#if defined(__clang_analyzer__) || defined(__COVERITY__)
/* If we're building for a static analysis, turn on all the off-by-default
* features. */
#ifndef INSTRUMENT_DOWNLOADS
@@ -1958,6 +1958,7 @@ typedef struct download_status_t {
uint8_t n_download_failures; /**< Number of failures trying to download the
* most recent descriptor. */
download_schedule_bitfield_t schedule : 8;
+
} download_status_t;
/** If n_download_failures is this high, the download can never happen. */
@@ -2149,9 +2150,6 @@ typedef struct routerstatus_t {
/** True iff this router is a version that, if it caches directory info,
* we can get microdescriptors from. */
unsigned int version_supports_microdesc_cache:1;
- /** True iff this router is a version that allows DATA cells to arrive on
- * a stream before it has sent a CONNECTED cell. */
- unsigned int version_supports_optimistic_data:1;
/** True iff this router has a version that allows it to accept EXTEND2
* cells */
unsigned int version_supports_extend2_cells:1;
@@ -3778,6 +3776,11 @@ typedef struct {
uint64_t AccountingMax; /**< How many bytes do we allow per accounting
* interval before hibernation? 0 for "never
* hibernate." */
+ /** How do we determine when our AccountingMax has been reached?
+ * "max" for when in or out reaches AccountingMax
+ * "sum for when in plus out reaches AccountingMax */
+ char *AccountingRule_option;
+ enum { ACCT_MAX, ACCT_SUM } AccountingRule;
/** Base64-encoded hash of accepted passwords for the control system. */
config_line_t *HashedControlPassword;
@@ -3910,8 +3913,11 @@ typedef struct {
* instead of a hostname. */
int WarnUnsafeSocks;
- /** If true, the user wants us to collect statistics on clients
+ /** If true, we're configured to collect statistics on clients
* requesting network statuses from us as directory. */
+ int DirReqStatistics_option;
+ /** Internal variable to remember whether we're actually acting on
+ * DirReqStatistics_option -- yes if it's set and we're a server, else no. */
int DirReqStatistics;
/** If true, the user wants us to collect statistics on port usage. */
@@ -4051,6 +4057,10 @@ typedef struct {
/** Minimum value for the Fast flag threshold on testing networks. */
uint64_t TestingMinFastFlagThreshold;
+ /** Relays in a testing network which should be voted Exit
+ * regardless of exit policy. */
+ routerset_t *TestingDirAuthVoteExit;
+
/** Relays in a testing network which should be voted Guard
* regardless of uptime and bandwidth. */
routerset_t *TestingDirAuthVoteGuard;
@@ -4988,7 +4998,8 @@ typedef enum was_router_added_t {
ROUTER_NOT_IN_CONSENSUS = -3,
ROUTER_NOT_IN_CONSENSUS_OR_NETWORKSTATUS = -4,
ROUTER_AUTHDIR_REJECTS = -5,
- ROUTER_WAS_NOT_WANTED = -6
+ ROUTER_WAS_NOT_WANTED = -6,
+ ROUTER_WAS_TOO_OLD = -7,
} was_router_added_t;
/********************************* routerparse.c ************************/
diff --git a/src/or/policies.c b/src/or/policies.c
index 535271ba3f..7090eda2c4 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -62,6 +62,13 @@ static const char *private_nets[] = {
NULL
};
+static int policies_parse_exit_policy_internal(config_line_t *cfg,
+ smartlist_t **dest,
+ int ipv6_exit,
+ int rejectprivate,
+ uint32_t local_address,
+ int add_default_policy);
+
/** Replace all "private" entries in *<b>policy</b> with their expanded
* equivalents. */
void
@@ -423,11 +430,9 @@ validate_addr_policies(const or_options_t *options, char **msg)
smartlist_t *addr_policy=NULL;
*msg = NULL;
- if (policies_parse_exit_policy(options->ExitPolicy, &addr_policy,
- options->IPv6Exit,
- options->ExitPolicyRejectPrivate, 0,
- !options->BridgeRelay))
+ if (policies_parse_exit_policy_from_options(options,0,&addr_policy)) {
REJECT("Error in ExitPolicy entry.");
+ }
/* The rest of these calls *append* to addr_policy. So don't actually
* use the results for anything other than checking if they parse! */
@@ -948,11 +953,12 @@ exit_policy_remove_redundancies(smartlist_t *dest)
* the functions used to parse the exit policy from a router descriptor,
* see router_add_exit_policy.
*/
-int
-policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
- int ipv6_exit,
- int rejectprivate, uint32_t local_address,
- int add_default_policy)
+static int
+policies_parse_exit_policy_internal(config_line_t *cfg, smartlist_t **dest,
+ int ipv6_exit,
+ int rejectprivate,
+ uint32_t local_address,
+ int add_default_policy)
{
if (!ipv6_exit) {
append_exit_policy_string(dest, "reject *6:*");
@@ -978,6 +984,68 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
return 0;
}
+/** Parse exit policy in <b>cfg</b> into <b>dest</b> smartlist.
+ *
+ * Add entry that rejects all IPv6 destinations unless
+ * <b>EXIT_POLICY_IPV6_ENABLED</b> bit is set in <b>options</b> bitmask.
+ *
+ * If <b>EXIT_POLICY_REJECT_PRIVATE</b> bit is set in <b>options</b>,
+ * do add entry that rejects all destinations in private subnetwork
+ * Tor is running in.
+ *
+ * Respectively, if <b>EXIT_POLICY_ADD_DEFAULT</b> bit is set, add
+ * default exit policy entries to <b>result</b> smartlist.
+ */
+int
+policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
+ exit_policy_parser_cfg_t options,
+ uint32_t local_address)
+{
+ int ipv6_enabled = (options & EXIT_POLICY_IPV6_ENABLED) ? 1 : 0;
+ int reject_private = (options & EXIT_POLICY_REJECT_PRIVATE) ? 1 : 0;
+ int add_default = (options & EXIT_POLICY_ADD_DEFAULT) ? 1 : 0;
+
+ return policies_parse_exit_policy_internal(cfg,dest,ipv6_enabled,
+ reject_private,
+ local_address,
+ add_default);
+}
+
+/** Parse <b>ExitPolicy</b> member of <b>or_options</b> into <b>result</b>
+ * smartlist.
+ * If <b>or_options->IPv6Exit</b> is false, add an entry that
+ * rejects all IPv6 destinations.
+ *
+ * If <b>or_options->ExitPolicyRejectPrivate</b> is true, add entry that
+ * rejects all destinations in the private subnetwork of machine Tor
+ * instance is running in.
+ *
+ * If <b>or_options->BridgeRelay</b> is false, add entries of default
+ * Tor exit policy into <b>result</b> smartlist.
+ */
+int
+policies_parse_exit_policy_from_options(const or_options_t *or_options,
+ uint32_t local_address,
+ smartlist_t **result)
+{
+ exit_policy_parser_cfg_t parser_cfg = 0;
+
+ if (or_options->IPv6Exit) {
+ parser_cfg |= EXIT_POLICY_IPV6_ENABLED;
+ }
+
+ if (or_options->ExitPolicyRejectPrivate) {
+ parser_cfg |= EXIT_POLICY_REJECT_PRIVATE;
+ }
+
+ if (!or_options->BridgeRelay) {
+ parser_cfg |= EXIT_POLICY_ADD_DEFAULT;
+ }
+
+ return policies_parse_exit_policy(or_options->ExitPolicy,result,
+ parser_cfg,local_address);
+}
+
/** Add "reject *:*" to the end of the policy in *<b>dest</b>, allocating
* *<b>dest</b> as needed. */
void
diff --git a/src/or/policies.h b/src/or/policies.h
index da1feaf02d..0b47b761ec 100644
--- a/src/or/policies.h
+++ b/src/or/policies.h
@@ -18,6 +18,12 @@
*/
#define POLICY_BUF_LEN 72
+#define EXIT_POLICY_IPV6_ENABLED (1 << 0)
+#define EXIT_POLICY_REJECT_PRIVATE (1 << 1)
+#define EXIT_POLICY_ADD_DEFAULT (1 << 2)
+
+typedef int exit_policy_parser_cfg_t;
+
int firewall_is_fascist_or(void);
int fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port);
int fascist_firewall_allows_or(const routerinfo_t *ri);
@@ -42,10 +48,18 @@ MOCK_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
uint16_t port, const node_t *node);
+/*
int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
int ipv6exit,
int rejectprivate, uint32_t local_address,
int add_default_policy);
+*/
+int policies_parse_exit_policy_from_options(const or_options_t *or_options,
+ uint32_t local_address,
+ smartlist_t **result);
+int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
+ exit_policy_parser_cfg_t options,
+ uint32_t local_address);
void policies_exit_policy_append_reject_star(smartlist_t **dest);
void addr_policy_append_reject_addr(smartlist_t **dest,
const tor_addr_t *addr);
diff --git a/src/or/relay.c b/src/or/relay.c
index d97c84fb07..d60d96e235 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -1718,7 +1718,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
if (circ->package_window + CIRCWINDOW_INCREMENT >
CIRCWINDOW_START_MAX) {
static struct ratelim_t client_warn_ratelim = RATELIM_INIT(600);
- log_fn_ratelim(&client_warn_ratelim, LOG_WARN, LD_PROTOCOL,
+ log_fn_ratelim(&client_warn_ratelim,LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Unexpected sendme cell from client. "
"Closing circ (window %d).",
circ->package_window);
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index fa4dc0d9c9..bc34695bc0 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -271,7 +271,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
extend_info_t *extend_info = rendcirc->build_state->chosen_exit;
int klen;
/* nul pads */
- set_uint32(tmp+v3_shift+1, tor_addr_to_ipv4h(&extend_info->addr));
+ set_uint32(tmp+v3_shift+1, tor_addr_to_ipv4n(&extend_info->addr));
set_uint16(tmp+v3_shift+5, htons(extend_info->port));
memcpy(tmp+v3_shift+7, extend_info->identity_digest, DIGEST_LEN);
klen = crypto_pk_asn1_encode(extend_info->onion_key,
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index aca9da198a..269cd65679 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -155,7 +155,7 @@ rend_compute_v2_desc_id(char *desc_id_out, const char *service_id,
}
/* Calculate current time-period. */
time_period = get_time_period(now, 0, service_id_binary);
- /* Calculate secret-id-part = h(time-period + replica). */
+ /* Calculate secret-id-part = h(time-period | replica). */
get_secret_id_part_bytes(secret_id_part, time_period, descriptor_cookie,
replica);
/* Calculate descriptor ID. */
@@ -556,7 +556,7 @@ rend_encode_v2_descriptors(smartlist_t *descs_out,
char desc_digest[DIGEST_LEN];
rend_encoded_v2_service_descriptor_t *enc =
tor_malloc_zero(sizeof(rend_encoded_v2_service_descriptor_t));
- /* Calculate secret-id-part = h(time-period + cookie + replica). */
+ /* Calculate secret-id-part = h(time-period | cookie | replica). */
get_secret_id_part_bytes(secret_id_part, time_period, descriptor_cookie,
k);
base32_encode(secret_id_part_base32, sizeof(secret_id_part_base32),
diff --git a/src/or/rendmid.c b/src/or/rendmid.c
index d89cdf6bed..1bcd17bc44 100644
--- a/src/or/rendmid.c
+++ b/src/or/rendmid.c
@@ -188,7 +188,7 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request,
"Unable to send INTRODUCE2 cell to Tor client.");
goto err;
}
- /* And sent an ack down Alice's circuit. Empty body means succeeded. */
+ /* And send an ack down Alice's circuit. Empty body means succeeded. */
if (relay_send_command_from_edge(0,TO_CIRCUIT(circ),
RELAY_COMMAND_INTRODUCE_ACK,
NULL,0,NULL)) {
@@ -199,7 +199,7 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request,
return 0;
err:
- /* Send the client an NACK */
+ /* Send the client a NACK */
nak_body[0] = 1;
if (relay_send_command_from_edge(0,TO_CIRCUIT(circ),
RELAY_COMMAND_INTRODUCE_ACK,
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 749d6fa880..31b612bb26 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -1754,7 +1754,7 @@ rend_service_parse_intro_for_v2(
/*
* We accept version 3 too so that the v3 parser can call this with
- * and adjusted buffer for the latter part of a v3 cell, which is
+ * an adjusted buffer for the latter part of a v3 cell, which is
* identical to a v2 cell.
*/
if (!(intro->version == 2 ||
diff --git a/src/or/router.c b/src/or/router.c
index 7bcc02ef39..bbbf9c4b84 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -488,7 +488,7 @@ init_curve25519_keypair_from_file(curve25519_keypair_t *keys_out,
if (curve25519_keypair_write_to_file(keys_out, fname, tag)<0) {
tor_log(severity, LD_FS,
"Couldn't write generated key to \"%s\".", fname);
- memset(keys_out, 0, sizeof(*keys_out));
+ memwipe(keys_out, 0, sizeof(*keys_out));
goto error;
}
} else {
@@ -917,7 +917,7 @@ init_keys(void)
}
if (mydesc) {
was_router_added_t added;
- ri = router_parse_entry_from_string(mydesc, NULL, 1, 0, NULL);
+ ri = router_parse_entry_from_string(mydesc, NULL, 1, 0, NULL, NULL);
if (!ri) {
log_err(LD_GENERAL,"Generated a routerinfo we couldn't parse.");
return -1;
@@ -1080,6 +1080,7 @@ decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port)
* they're confused or to get statistics. */
int interval_length = accounting_get_interval_length();
uint32_t effective_bw = get_effective_bwrate(options);
+ uint64_t acc_bytes;
if (!interval_length) {
log_warn(LD_BUG, "An accounting interval is not allowed to be zero "
"seconds long. Raising to 1.");
@@ -1090,8 +1091,12 @@ decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port)
"accounting interval length %d", effective_bw,
U64_PRINTF_ARG(options->AccountingMax),
interval_length);
+
+ acc_bytes = options->AccountingMax;
+ if (get_options()->AccountingRule == ACCT_SUM)
+ acc_bytes /= 2;
if (effective_bw >=
- options->AccountingMax / interval_length) {
+ acc_bytes / interval_length) {
new_choice = 0;
reason = "AccountingMax enabled";
}
@@ -1855,10 +1860,8 @@ router_rebuild_descriptor(int force)
/* DNS is screwed up; don't claim to be an exit. */
policies_exit_policy_append_reject_star(&ri->exit_policy);
} else {
- policies_parse_exit_policy(options->ExitPolicy, &ri->exit_policy,
- options->IPv6Exit,
- options->ExitPolicyRejectPrivate,
- ri->addr, !options->BridgeRelay);
+ policies_parse_exit_policy_from_options(options,ri->addr,
+ &ri->exit_policy);
}
ri->policy_is_reject_star =
policy_is_reject_star(ri->exit_policy, AF_INET) &&
@@ -2444,7 +2447,7 @@ router_dump_router_to_string(routerinfo_t *router,
const char *cp;
routerinfo_t *ri_tmp;
cp = s_dup = tor_strdup(output);
- ri_tmp = router_parse_entry_from_string(cp, NULL, 1, 0, NULL);
+ ri_tmp = router_parse_entry_from_string(cp, NULL, 1, 0, NULL, NULL);
if (!ri_tmp) {
log_err(LD_BUG,
"We just generated a router descriptor we can't parse.");
@@ -2726,7 +2729,7 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
s = smartlist_join_strings(chunks, "", 0, NULL);
cp = s_dup = tor_strdup(s);
- ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL);
+ ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL, NULL);
if (!ei_tmp) {
if (write_stats_to_extrainfo) {
log_warn(LD_GENERAL, "We just generated an extra-info descriptor "
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 697837e509..5748dfd5f4 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -475,6 +475,8 @@ trusted_dirs_remove_old_certs(void)
time_t cert_published;
if (newest == cert)
continue;
+ /* resolve spurious clang shallow analysis null pointer errors */
+ tor_assert(cert);
expired = now > cert->expires;
cert_published = cert->cache_info.published_on;
/* Store expired certs for 48 hours after a newer arrives;
@@ -1804,7 +1806,7 @@ scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
uint64_t *total_out)
{
double total = 0.0;
- double scale_factor;
+ double scale_factor = 0.0;
int i;
/* big, but far away from overflowing an int64_t */
#define SCALE_TO_U64_MAX ((int64_t) (INT64_MAX / 4))
@@ -1812,7 +1814,8 @@ scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
for (i = 0; i < n_entries; ++i)
total += entries[i].dbl;
- scale_factor = SCALE_TO_U64_MAX / total;
+ if (total > 0.0)
+ scale_factor = SCALE_TO_U64_MAX / total;
for (i = 0; i < n_entries; ++i)
entries[i].u64 = tor_llround(entries[i].dbl * scale_factor);
@@ -2531,7 +2534,7 @@ router_is_named(const routerinfo_t *router)
/** Return true iff <b>digest</b> is the digest of the identity key of a
* trusted directory matching at least one bit of <b>type</b>. If <b>type</b>
- * is zero, any authority is okay. */
+ * is zero (NO_DIRINFO), or ALL_DIRINFO, any authority is okay. */
int
router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
{
@@ -2612,8 +2615,8 @@ router_get_by_descriptor_digest(const char *digest)
/** Return the signed descriptor for the router in our routerlist whose
* 20-byte extra-info digest is <b>digest</b>. Return NULL if no such router
* is known. */
-signed_descriptor_t *
-router_get_by_extrainfo_digest(const char *digest)
+MOCK_IMPL(signed_descriptor_t *,
+router_get_by_extrainfo_digest,(const char *digest))
{
tor_assert(digest);
@@ -2934,12 +2937,12 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
}
/** Adds the extrainfo_t <b>ei</b> to the routerlist <b>rl</b>, if there is a
- * corresponding router in rl-\>routers or rl-\>old_routers. Return true iff
- * we actually inserted <b>ei</b>. Free <b>ei</b> if it isn't inserted. */
-static int
-extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
+ * corresponding router in rl-\>routers or rl-\>old_routers. Return the status
+ * of inserting <b>ei</b>. Free <b>ei</b> if it isn't inserted. */
+MOCK_IMPL(STATIC was_router_added_t,
+extrainfo_insert,(routerlist_t *rl, extrainfo_t *ei))
{
- int r = 0;
+ was_router_added_t r;
routerinfo_t *ri = rimap_get(rl->identity_map,
ei->cache_info.identity_digest);
signed_descriptor_t *sd =
@@ -2953,9 +2956,11 @@ extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
if (!ri) {
/* This router is unknown; we can't even verify the signature. Give up.*/
+ r = ROUTER_NOT_IN_CONSENSUS;
goto done;
}
if (routerinfo_incompatible_with_extrainfo(ri, ei, sd, NULL)) {
+ r = (sd->extrainfo_is_bogus) ? ROUTER_BAD_EI : ROUTER_NOT_IN_CONSENSUS;
goto done;
}
@@ -2965,7 +2970,7 @@ extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
ei_tmp = eimap_set(rl->extra_info_map,
ei->cache_info.signed_descriptor_digest,
ei);
- r = 1;
+ r = ROUTER_ADDED_SUCCESSFULLY;
if (ei_tmp) {
rl->extrainfo_store.bytes_dropped +=
ei_tmp->cache_info.signed_descriptor_len;
@@ -2973,7 +2978,7 @@ extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
}
done:
- if (r == 0)
+ if (r != ROUTER_ADDED_SUCCESSFULLY)
extrainfo_free(ei);
#ifdef DEBUG_ROUTERLIST
@@ -3248,7 +3253,7 @@ routerlist_reparse_old(routerlist_t *rl, signed_descriptor_t *sd)
ri = router_parse_entry_from_string(body,
body+sd->signed_descriptor_len+sd->annotations_len,
- 0, 1, NULL);
+ 0, 1, NULL, NULL);
if (!ri)
return NULL;
memcpy(&ri->cache_info, sd, sizeof(signed_descriptor_t));
@@ -3299,7 +3304,7 @@ routerlist_reset_warnings(void)
MOCK_IMPL(int,
router_descriptor_is_older_than,(const routerinfo_t *router, int seconds))
{
- return router->cache_info.published_on < time(NULL) - seconds;
+ return router->cache_info.published_on < approx_time() - seconds;
}
/** Add <b>router</b> to the routerlist, if we don't already have it. Replace
@@ -3474,7 +3479,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
router_descriptor_is_older_than(router, OLD_ROUTER_DESC_MAX_AGE)) {
*msg = "Router descriptor was really old.";
routerinfo_free(router);
- return ROUTER_WAS_NOT_NEW;
+ return ROUTER_WAS_TOO_OLD;
}
/* We haven't seen a router with this identity before. Add it to the end of
@@ -3495,21 +3500,18 @@ was_router_added_t
router_add_extrainfo_to_routerlist(extrainfo_t *ei, const char **msg,
int from_cache, int from_fetch)
{
- int inserted;
+ was_router_added_t inserted;
(void)from_fetch;
if (msg) *msg = NULL;
/*XXXX023 Do something with msg */
inserted = extrainfo_insert(router_get_routerlist(), ei);
- if (inserted && !from_cache)
+ if (WRA_WAS_ADDED(inserted) && !from_cache)
signed_desc_append_to_journal(&ei->cache_info,
&routerlist->extrainfo_store);
- if (inserted)
- return ROUTER_ADDED_SUCCESSFULLY;
- else
- return ROUTER_BAD_EI;
+ return inserted;
}
/** Sorting helper: return &lt;0, 0, or &gt;0 depending on whether the
@@ -3804,7 +3806,8 @@ router_load_single_router(const char *s, uint8_t purpose, int cache,
"@source controller\n"
"@purpose %s\n", router_purpose_to_string(purpose));
- if (!(ri = router_parse_entry_from_string(s, NULL, 1, 0, annotation_buf))) {
+ if (!(ri = router_parse_entry_from_string(s, NULL, 1, 0,
+ annotation_buf, NULL))) {
log_warn(LD_DIR, "Error parsing router descriptor; dropping.");
*msg = "Couldn't parse router descriptor.";
return -1;
@@ -3868,9 +3871,11 @@ router_load_routers_from_string(const char *s, const char *eos,
int from_cache = (saved_location != SAVED_NOWHERE);
int allow_annotations = (saved_location != SAVED_NOWHERE);
int any_changed = 0;
+ smartlist_t *invalid_digests = smartlist_new();
router_parse_list_from_string(&s, eos, routers, saved_location, 0,
- allow_annotations, prepend_annotations);
+ allow_annotations, prepend_annotations,
+ invalid_digests);
routers_update_status_from_consensus_networkstatus(routers, !from_cache);
@@ -3906,7 +3911,7 @@ router_load_routers_from_string(const char *s, const char *eos,
smartlist_add(changed, ri);
routerlist_descriptors_added(changed, from_cache);
smartlist_clear(changed);
- } else if (WRA_WAS_REJECTED(r)) {
+ } else if (WRA_NEVER_DOWNLOADABLE(r)) {
download_status_t *dl_status;
dl_status = router_get_dl_status_by_descriptor_digest(d);
if (dl_status) {
@@ -3917,6 +3922,27 @@ router_load_routers_from_string(const char *s, const char *eos,
}
} SMARTLIST_FOREACH_END(ri);
+ SMARTLIST_FOREACH_BEGIN(invalid_digests, const uint8_t *, bad_digest) {
+ /* This digest is never going to be parseable. */
+ base16_encode(fp, sizeof(fp), (char*)bad_digest, DIGEST_LEN);
+ if (requested_fingerprints && descriptor_digests) {
+ if (! smartlist_contains_string(requested_fingerprints, fp)) {
+ /* But we didn't ask for it, so we should assume shennanegans. */
+ continue;
+ }
+ smartlist_string_remove(requested_fingerprints, fp);
+ }
+ download_status_t *dls;
+ dls = router_get_dl_status_by_descriptor_digest((char*)bad_digest);
+ if (dls) {
+ log_info(LD_GENERAL, "Marking router with descriptor %s as unparseable, "
+ "and therefore undownloadable", fp);
+ download_status_mark_impossible(dls);
+ }
+ } SMARTLIST_FOREACH_END(bad_digest);
+ SMARTLIST_FOREACH(invalid_digests, uint8_t *, d, tor_free(d));
+ smartlist_free(invalid_digests);
+
routerlist_assert_ok(routerlist);
if (any_changed)
@@ -3940,13 +3966,16 @@ router_load_extrainfo_from_string(const char *s, const char *eos,
smartlist_t *extrainfo_list = smartlist_new();
const char *msg;
int from_cache = (saved_location != SAVED_NOWHERE);
+ smartlist_t *invalid_digests = smartlist_new();
router_parse_list_from_string(&s, eos, extrainfo_list, saved_location, 1, 0,
- NULL);
+ NULL, invalid_digests);
log_info(LD_DIR, "%d elements to add", smartlist_len(extrainfo_list));
SMARTLIST_FOREACH_BEGIN(extrainfo_list, extrainfo_t *, ei) {
+ uint8_t d[DIGEST_LEN];
+ memcpy(d, ei->cache_info.signed_descriptor_digest, DIGEST_LEN);
was_router_added_t added =
router_add_extrainfo_to_routerlist(ei, &msg, from_cache, !from_cache);
if (WRA_WAS_ADDED(added) && requested_fingerprints) {
@@ -3960,9 +3989,39 @@ router_load_extrainfo_from_string(const char *s, const char *eos,
* so long as we would have wanted them anyway. Since we always fetch
* all the extrainfos we want, and we never actually act on them
* inside Tor, this should be harmless. */
+ } else if (WRA_NEVER_DOWNLOADABLE(added)) {
+ signed_descriptor_t *sd = router_get_by_extrainfo_digest((char*)d);
+ if (sd) {
+ log_info(LD_GENERAL, "Marking extrainfo with descriptor %s as "
+ "unparseable, and therefore undownloadable",
+ hex_str((char*)d,DIGEST_LEN));
+ download_status_mark_impossible(&sd->ei_dl_status);
+ }
}
} SMARTLIST_FOREACH_END(ei);
+ SMARTLIST_FOREACH_BEGIN(invalid_digests, const uint8_t *, bad_digest) {
+ /* This digest is never going to be parseable. */
+ char fp[HEX_DIGEST_LEN+1];
+ base16_encode(fp, sizeof(fp), (char*)bad_digest, DIGEST_LEN);
+ if (requested_fingerprints) {
+ if (! smartlist_contains_string(requested_fingerprints, fp)) {
+ /* But we didn't ask for it, so we should assume shennanegans. */
+ continue;
+ }
+ smartlist_string_remove(requested_fingerprints, fp);
+ }
+ signed_descriptor_t *sd =
+ router_get_by_extrainfo_digest((char*)bad_digest);
+ if (sd) {
+ log_info(LD_GENERAL, "Marking extrainfo with descriptor %s as "
+ "unparseable, and therefore undownloadable", fp);
+ download_status_mark_impossible(&sd->ei_dl_status);
+ }
+ } SMARTLIST_FOREACH_END(bad_digest);
+ SMARTLIST_FOREACH(invalid_digests, uint8_t *, d, tor_free(d));
+ smartlist_free(invalid_digests);
+
routerlist_assert_ok(routerlist);
router_rebuild_store(0, &router_get_routerlist()->extrainfo_store);
@@ -4948,7 +5007,7 @@ routerlist_assert_ok(const routerlist_t *rl)
} SMARTLIST_FOREACH_END(r);
SMARTLIST_FOREACH_BEGIN(rl->old_routers, signed_descriptor_t *, sd) {
r2 = rimap_get(rl->identity_map, sd->identity_digest);
- tor_assert(sd != &(r2->cache_info));
+ tor_assert(!r2 || sd != &(r2->cache_info));
sd2 = sdmap_get(rl->desc_digest_map, sd->signed_descriptor_digest);
tor_assert(sd == sd2);
tor_assert(sd->routerlist_index == sd_sl_idx);
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index 52f2303c7c..a0f43d430c 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -82,7 +82,8 @@ int hexdigest_to_digest(const char *hexdigest, char *digest);
const routerinfo_t *router_get_by_id_digest(const char *digest);
routerinfo_t *router_get_mutable_by_digest(const char *digest);
signed_descriptor_t *router_get_by_descriptor_digest(const char *digest);
-signed_descriptor_t *router_get_by_extrainfo_digest(const char *digest);
+MOCK_DECL(signed_descriptor_t *,router_get_by_extrainfo_digest,
+ (const char *digest));
signed_descriptor_t *extrainfo_get_by_descriptor_digest(const char *digest);
const char *signed_descriptor_get_body(const signed_descriptor_t *desc);
const char *signed_descriptor_get_annotations(const signed_descriptor_t *desc);
@@ -99,6 +100,7 @@ void routerlist_reset_warnings(void);
static int WRA_WAS_ADDED(was_router_added_t s);
static int WRA_WAS_OUTDATED(was_router_added_t s);
static int WRA_WAS_REJECTED(was_router_added_t s);
+static int WRA_NEVER_DOWNLOADABLE(was_router_added_t s);
/** Return true iff the outcome code in <b>s</b> indicates that the descriptor
* was added. It might still be necessary to check whether the descriptor
* generator should be notified.
@@ -115,7 +117,8 @@ WRA_WAS_ADDED(was_router_added_t s) {
*/
static INLINE int WRA_WAS_OUTDATED(was_router_added_t s)
{
- return (s == ROUTER_WAS_NOT_NEW ||
+ return (s == ROUTER_WAS_TOO_OLD ||
+ s == ROUTER_WAS_NOT_NEW ||
s == ROUTER_NOT_IN_CONSENSUS ||
s == ROUTER_NOT_IN_CONSENSUS_OR_NETWORKSTATUS);
}
@@ -125,6 +128,14 @@ static INLINE int WRA_WAS_REJECTED(was_router_added_t s)
{
return (s == ROUTER_AUTHDIR_REJECTS);
}
+/** Return true iff the outcome code in <b>s</b> indicates that the descriptor
+ * was flat-out rejected. */
+static INLINE int WRA_NEVER_DOWNLOADABLE(was_router_added_t s)
+{
+ return (s == ROUTER_AUTHDIR_REJECTS ||
+ s == ROUTER_BAD_EI ||
+ s == ROUTER_WAS_TOO_OLD);
+}
was_router_added_t router_add_to_routerlist(routerinfo_t *router,
const char **msg,
int from_cache,
@@ -215,6 +226,9 @@ STATIC void scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
MOCK_DECL(int, router_descriptor_is_older_than, (const routerinfo_t *router,
int seconds));
+MOCK_DECL(STATIC was_router_added_t, extrainfo_insert,
+ (routerlist_t *rl, extrainfo_t *ei));
+
#endif
#endif
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 281341d134..76eef789f0 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -911,7 +911,9 @@ find_start_of_next_router_or_extrainfo(const char **s_ptr,
* descriptor in the signed_descriptor_body field of each routerinfo_t. If it
* isn't SAVED_NOWHERE, remember the offset of each descriptor.
*
- * Returns 0 on success and -1 on failure.
+ * Returns 0 on success and -1 on failure. Adds a digest to
+ * <b>invalid_digests_out</b> for every entry that was unparseable or
+ * invalid. (This may cause duplicate entries.)
*/
int
router_parse_list_from_string(const char **s, const char *eos,
@@ -919,7 +921,8 @@ router_parse_list_from_string(const char **s, const char *eos,
saved_location_t saved_location,
int want_extrainfo,
int allow_annotations,
- const char *prepend_annotations)
+ const char *prepend_annotations,
+ smartlist_t *invalid_digests_out)
{
routerinfo_t *router;
extrainfo_t *extrainfo;
@@ -939,6 +942,9 @@ router_parse_list_from_string(const char **s, const char *eos,
tor_assert(eos >= *s);
while (1) {
+ char raw_digest[DIGEST_LEN];
+ int have_raw_digest = 0;
+ int dl_again = 0;
if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
break;
@@ -955,18 +961,20 @@ router_parse_list_from_string(const char **s, const char *eos,
if (have_extrainfo && want_extrainfo) {
routerlist_t *rl = router_get_routerlist();
+ have_raw_digest = router_get_extrainfo_hash(*s, end-*s, raw_digest) == 0;
extrainfo = extrainfo_parse_entry_from_string(*s, end,
saved_location != SAVED_IN_CACHE,
- rl->identity_map);
+ rl->identity_map, &dl_again);
if (extrainfo) {
signed_desc = &extrainfo->cache_info;
elt = extrainfo;
}
} else if (!have_extrainfo && !want_extrainfo) {
+ have_raw_digest = router_get_router_hash(*s, end-*s, raw_digest) == 0;
router = router_parse_entry_from_string(*s, end,
saved_location != SAVED_IN_CACHE,
allow_annotations,
- prepend_annotations);
+ prepend_annotations, &dl_again);
if (router) {
log_debug(LD_DIR, "Read router '%s', purpose '%s'",
router_describe(router),
@@ -975,6 +983,9 @@ router_parse_list_from_string(const char **s, const char *eos,
elt = router;
}
}
+ if (! elt && ! dl_again && have_raw_digest && invalid_digests_out) {
+ smartlist_add(invalid_digests_out, tor_memdup(raw_digest, DIGEST_LEN));
+ }
if (!elt) {
*s = end;
continue;
@@ -1068,11 +1079,17 @@ find_single_ipv6_orport(const smartlist_t *list,
* around when caching the router.
*
* Only one of allow_annotations and prepend_annotations may be set.
+ *
+ * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
+ * if it's okay to try to download a descriptor with this same digest again,
+ * and 0 if it isn't. (It might not be okay to download it again if part of
+ * the part covered by the digest is invalid.)
*/
routerinfo_t *
router_parse_entry_from_string(const char *s, const char *end,
int cache_copy, int allow_annotations,
- const char *prepend_annotations)
+ const char *prepend_annotations,
+ int *can_dl_again_out)
{
routerinfo_t *router = NULL;
char digest[128];
@@ -1083,6 +1100,9 @@ router_parse_entry_from_string(const char *s, const char *end,
size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
int ok = 1;
memarea_t *area = NULL;
+ /* Do not set this to '1' until we have parsed everything that we intend to
+ * parse that's covered by the hash. */
+ int can_dl_again = 0;
tor_assert(!allow_annotations || !prepend_annotations);
@@ -1389,19 +1409,21 @@ router_parse_entry_from_string(const char *s, const char *end,
verified_digests = digestmap_new();
digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1);
#endif
- if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0,
- "router descriptor") < 0)
- goto err;
if (!router->or_port) {
log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
goto err;
}
+ /* We've checked everything that's covered by the hash. */
+ can_dl_again = 1;
+ if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0,
+ "router descriptor") < 0)
+ goto err;
+
if (!router->platform) {
router->platform = tor_strdup("<unknown>");
}
-
goto done;
err:
@@ -1418,6 +1440,8 @@ router_parse_entry_from_string(const char *s, const char *end,
DUMP_AREA(area, "routerinfo");
memarea_drop_all(area);
}
+ if (can_dl_again_out)
+ *can_dl_again_out = can_dl_again;
return router;
}
@@ -1426,10 +1450,16 @@ router_parse_entry_from_string(const char *s, const char *end,
* <b>cache_copy</b> is true, make a copy of the extra-info document in the
* cache_info fields of the result. If <b>routermap</b> is provided, use it
* as a map from router identity to routerinfo_t when looking up signing keys.
+ *
+ * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
+ * if it's okay to try to download an extrainfo with this same digest again,
+ * and 0 if it isn't. (It might not be okay to download it again if part of
+ * the part covered by the digest is invalid.)
*/
extrainfo_t *
extrainfo_parse_entry_from_string(const char *s, const char *end,
- int cache_copy, struct digest_ri_map_t *routermap)
+ int cache_copy, struct digest_ri_map_t *routermap,
+ int *can_dl_again_out)
{
extrainfo_t *extrainfo = NULL;
char digest[128];
@@ -1439,6 +1469,9 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
routerinfo_t *router = NULL;
memarea_t *area = NULL;
const char *s_dup = s;
+ /* Do not set this to '1' until we have parsed everything that we intend to
+ * parse that's covered by the hash. */
+ int can_dl_again = 0;
if (!end) {
end = s + strlen(s);
@@ -1498,6 +1531,9 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
goto err;
}
+ /* We've checked everything that's covered by the hash. */
+ can_dl_again = 1;
+
if (routermap &&
(router = digestmap_get((digestmap_t*)routermap,
extrainfo->cache_info.identity_digest))) {
@@ -1540,6 +1576,8 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
DUMP_AREA(area, "extrainfo");
memarea_drop_all(area);
}
+ if (can_dl_again_out)
+ *can_dl_again_out = can_dl_again;
return extrainfo;
}
@@ -1916,12 +1954,9 @@ routerstatus_parse_entry_from_string(memarea_t *area,
rs->version_known = 1;
if (strcmpstart(tok->args[0], "Tor ")) {
rs->version_supports_microdesc_cache = 1;
- rs->version_supports_optimistic_data = 1;
} else {
rs->version_supports_microdesc_cache =
tor_version_supports_microdescriptors(tok->args[0]);
- rs->version_supports_optimistic_data =
- tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha");
rs->version_supports_extend2_cells =
tor_version_as_new_as(tok->args[0], "0.2.4.8-alpha");
}
@@ -4009,12 +4044,15 @@ find_start_of_next_microdesc(const char *s, const char *eos)
* If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
* descriptor in the body field of each microdesc_t.
*
- * Return all newly
- * parsed microdescriptors in a newly allocated smartlist_t. */
+ * Return all newly parsed microdescriptors in a newly allocated
+ * smartlist_t. If <b>invalid_disgests_out</b> is provided, add a SHA256
+ * microdesc digest to it for every microdesc that we found to be badly
+ * formed. (This may cause duplicates) */
smartlist_t *
microdescs_parse_from_string(const char *s, const char *eos,
int allow_annotations,
- saved_location_t where)
+ saved_location_t where,
+ smartlist_t *invalid_digests_out)
{
smartlist_t *tokens;
smartlist_t *result;
@@ -4036,16 +4074,12 @@ microdescs_parse_from_string(const char *s, const char *eos,
tokens = smartlist_new();
while (s < eos) {
+ int okay = 0;
+
start_of_next_microdesc = find_start_of_next_microdesc(s, eos);
if (!start_of_next_microdesc)
start_of_next_microdesc = eos;
- if (tokenize_string(area, s, start_of_next_microdesc, tokens,
- microdesc_token_table, flags)) {
- log_warn(LD_DIR, "Unparseable microdescriptor");
- goto next;
- }
-
md = tor_malloc_zero(sizeof(microdesc_t));
{
const char *cp = tor_memstr(s, start_of_next_microdesc-s,
@@ -4060,6 +4094,13 @@ microdescs_parse_from_string(const char *s, const char *eos,
md->body = (char*)cp;
md->off = cp - start;
}
+ crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
+
+ if (tokenize_string(area, s, start_of_next_microdesc, tokens,
+ microdesc_token_table, flags)) {
+ log_warn(LD_DIR, "Unparseable microdescriptor");
+ goto next;
+ }
if ((tok = find_opt_by_keyword(tokens, A_LAST_LISTED))) {
if (parse_iso_time(tok->args[0], &md->last_listed)) {
@@ -4116,12 +4157,15 @@ microdescs_parse_from_string(const char *s, const char *eos,
md->ipv6_exit_policy = parse_short_policy(tok->args[0]);
}
- crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
-
smartlist_add(result, md);
+ okay = 1;
md = NULL;
next:
+ if (! okay && invalid_digests_out) {
+ smartlist_add(invalid_digests_out,
+ tor_memdup(md->digest, DIGEST256_LEN));
+ }
microdesc_free(md);
md = NULL;
diff --git a/src/or/routerparse.h b/src/or/routerparse.h
index fa275c8265..927d0b50a7 100644
--- a/src/or/routerparse.h
+++ b/src/or/routerparse.h
@@ -29,14 +29,17 @@ int router_parse_list_from_string(const char **s, const char *eos,
saved_location_t saved_location,
int is_extrainfo,
int allow_annotations,
- const char *prepend_annotations);
+ const char *prepend_annotations,
+ smartlist_t *invalid_digests_out);
routerinfo_t *router_parse_entry_from_string(const char *s, const char *end,
int cache_copy,
int allow_annotations,
- const char *prepend_annotations);
+ const char *prepend_annotations,
+ int *can_dl_again_out);
extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end,
- int cache_copy, struct digest_ri_map_t *routermap);
+ int cache_copy, struct digest_ri_map_t *routermap,
+ int *can_dl_again_out);
MOCK_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
(const char *s, int assume_action));
version_status_t tor_version_is_obsolete(const char *myversion,
@@ -60,7 +63,8 @@ ns_detached_signatures_t *networkstatus_parse_detached_signatures(
smartlist_t *microdescs_parse_from_string(const char *s, const char *eos,
int allow_annotations,
- saved_location_t where);
+ saved_location_t where,
+ smartlist_t *invalid_digests_out);
authority_cert_t *authority_cert_parse_from_string(const char *s,
const char **end_of_string);
diff --git a/src/or/status.c b/src/or/status.c
index c4156d0cc3..daae1d71c6 100644
--- a/src/or/status.c
+++ b/src/or/status.c
@@ -145,10 +145,14 @@ log_accounting(const time_t now, const or_options_t *options)
or_state_t *state = get_or_state();
char *acc_rcvd = bytes_to_usage(state->AccountingBytesReadInInterval);
char *acc_sent = bytes_to_usage(state->AccountingBytesWrittenInInterval);
- char *acc_max = bytes_to_usage(options->AccountingMax);
+ uint64_t acc_bytes = options->AccountingMax;
+ char *acc_max;
time_t interval_end = accounting_get_end_time();
char end_buf[ISO_TIME_LEN + 1];
char *remaining = NULL;
+ if (options->AccountingRule == ACCT_SUM)
+ acc_bytes *= 2;
+ acc_max = bytes_to_usage(acc_bytes);
format_local_iso_time(end_buf, interval_end);
remaining = secs_to_uptime(interval_end - now);
diff --git a/src/or/transports.c b/src/or/transports.c
index dc30754162..5c7c0b7130 100644
--- a/src/or/transports.c
+++ b/src/or/transports.c
@@ -124,6 +124,8 @@ static INLINE void free_execve_args(char **arg);
#define PROTO_SMETHOD_ERROR "SMETHOD-ERROR"
#define PROTO_CMETHODS_DONE "CMETHODS DONE"
#define PROTO_SMETHODS_DONE "SMETHODS DONE"
+#define PROTO_PROXY_DONE "PROXY DONE"
+#define PROTO_PROXY_ERROR "PROXY-ERROR"
/** The first and only supported - at the moment - configuration
protocol version. */
@@ -439,6 +441,17 @@ add_transport_to_proxy(const char *transport, managed_proxy_t *mp)
static int
proxy_needs_restart(const managed_proxy_t *mp)
{
+ int ret = 1;
+ char* proxy_uri;
+
+ /* If the PT proxy config has changed, then all existing pluggable transports
+ * should be restarted.
+ */
+
+ proxy_uri = get_pt_proxy_uri();
+ if (strcmp_opt(proxy_uri, mp->proxy_uri) != 0)
+ goto needs_restart;
+
/* mp->transport_to_launch is populated with the names of the
transports that must be launched *after* the SIGHUP.
mp->transports is populated with the transports that were
@@ -459,10 +472,10 @@ proxy_needs_restart(const managed_proxy_t *mp)
} SMARTLIST_FOREACH_END(t);
- return 0;
-
+ ret = 0;
needs_restart:
- return 1;
+ tor_free(proxy_uri);
+ return ret;
}
/** Managed proxy <b>mp</b> must be restarted. Do all the necessary
@@ -493,6 +506,11 @@ proxy_prepare_for_restart(managed_proxy_t *mp)
SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
smartlist_clear(mp->transports);
+ /* Reset the proxy's HTTPS/SOCKS proxy */
+ tor_free(mp->proxy_uri);
+ mp->proxy_uri = get_pt_proxy_uri();
+ mp->proxy_supported = 0;
+
/* flag it as an infant proxy so that it gets launched on next tick */
mp->conf_state = PT_PROTO_INFANT;
unconfigured_proxies_n++;
@@ -727,12 +745,54 @@ managed_proxy_destroy(managed_proxy_t *mp,
/* free the argv */
free_execve_args(mp->argv);
+ /* free the outgoing proxy URI */
+ tor_free(mp->proxy_uri);
+
tor_process_handle_destroy(mp->process_handle, also_terminate_process);
mp->process_handle = NULL;
tor_free(mp);
}
+/** Convert the tor proxy options to a URI suitable for TOR_PT_PROXY.
+ * Return a newly allocated string containing the URI, or NULL if no
+ * proxy is set. */
+STATIC char *
+get_pt_proxy_uri(void)
+{
+ const or_options_t *options = get_options();
+ char *uri = NULL;
+
+ if (options->Socks4Proxy || options->Socks5Proxy || options->HTTPSProxy) {
+ char addr[TOR_ADDR_BUF_LEN+1];
+
+ if (options->Socks4Proxy) {
+ tor_addr_to_str(addr, &options->Socks4ProxyAddr, sizeof(addr), 1);
+ tor_asprintf(&uri, "socks4a://%s:%d", addr, options->Socks4ProxyPort);
+ } else if (options->Socks5Proxy) {
+ tor_addr_to_str(addr, &options->Socks5ProxyAddr, sizeof(addr), 1);
+ if (!options->Socks5ProxyUsername && !options->Socks5ProxyPassword) {
+ tor_asprintf(&uri, "socks5://%s:%d", addr, options->Socks5ProxyPort);
+ } else {
+ tor_asprintf(&uri, "socks5://%s:%s@%s:%d",
+ options->Socks5ProxyUsername,
+ options->Socks5ProxyPassword,
+ addr, options->Socks5ProxyPort);
+ }
+ } else if (options->HTTPSProxy) {
+ tor_addr_to_str(addr, &options->HTTPSProxyAddr, sizeof(addr), 1);
+ if (!options->HTTPSProxyAuthenticator) {
+ tor_asprintf(&uri, "http://%s:%d", addr, options->HTTPSProxyPort);
+ } else {
+ tor_asprintf(&uri, "http://%s@%s:%d", options->HTTPSProxyAuthenticator,
+ addr, options->HTTPSProxyPort);
+ }
+ }
+ }
+
+ return uri;
+}
+
/** Handle a configured or broken managed proxy <b>mp</b>. */
static void
handle_finished_proxy(managed_proxy_t *mp)
@@ -745,6 +805,13 @@ handle_finished_proxy(managed_proxy_t *mp)
managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */
break;
case PT_PROTO_CONFIGURED: /* if configured correctly: */
+ if (mp->proxy_uri && !mp->proxy_supported) {
+ log_warn(LD_CONFIG, "Managed proxy '%s' did not configure the "
+ "specified outgoing proxy and will be terminated.",
+ mp->argv[0]);
+ managed_proxy_destroy(mp, 1); /* annihilate it. */
+ break;
+ }
register_proxy(mp); /* register its transports */
mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */
break;
@@ -862,6 +929,22 @@ handle_proxy_line(const char *line, managed_proxy_t *mp)
goto err;
return;
+ } else if (!strcmpstart(line, PROTO_PROXY_DONE)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ if (mp->proxy_uri) {
+ mp->proxy_supported = 1;
+ return;
+ }
+
+ /* No proxy was configured, this should log */
+ } else if (!strcmpstart(line, PROTO_PROXY_ERROR)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ parse_proxy_error(line);
+ goto err;
} else if (!strcmpstart(line, SPAWN_ERROR_MESSAGE)) {
/* managed proxy launch failed: parse error message to learn why. */
int retval, child_state, saved_errno;
@@ -1128,6 +1211,21 @@ parse_cmethod_line(const char *line, managed_proxy_t *mp)
return r;
}
+/** Parses an PROXY-ERROR <b>line</b> and warns the user accordingly. */
+STATIC void
+parse_proxy_error(const char *line)
+{
+ /* (Length of the protocol string) plus (a space) and (the first char of
+ the error message) */
+ if (strlen(line) < (strlen(PROTO_PROXY_ERROR) + 2))
+ log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
+ "message.", PROTO_PROXY_ERROR);
+
+ log_warn(LD_CONFIG, "Managed proxy failed to configure the "
+ "pluggable transport's outgoing proxy. (%s)",
+ line+strlen(PROTO_PROXY_ERROR)+1);
+}
+
/** Return a newly allocated string that tor should place in
* TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server
* manged proxy in <b>mp</b>. Return NULL if no such options are found. */
@@ -1292,6 +1390,14 @@ create_managed_proxy_environment(const managed_proxy_t *mp)
} else {
smartlist_add_asprintf(envs, "TOR_PT_EXTENDED_SERVER_PORT=");
}
+ } else {
+ /* If ClientTransportPlugin has a HTTPS/SOCKS proxy configured, set the
+ * TOR_PT_PROXY line.
+ */
+
+ if (mp->proxy_uri) {
+ smartlist_add_asprintf(envs, "TOR_PT_PROXY=%s", mp->proxy_uri);
+ }
}
SMARTLIST_FOREACH_BEGIN(envs, const char *, env_var) {
@@ -1324,6 +1430,7 @@ managed_proxy_create(const smartlist_t *transport_list,
mp->is_server = is_server;
mp->argv = proxy_argv;
mp->transports = smartlist_new();
+ mp->proxy_uri = get_pt_proxy_uri();
mp->transports_to_launch = smartlist_new();
SMARTLIST_FOREACH(transport_list, const char *, transport,
diff --git a/src/or/transports.h b/src/or/transports.h
index 1365ead006..25fe5a29a9 100644
--- a/src/or/transports.h
+++ b/src/or/transports.h
@@ -81,6 +81,9 @@ typedef struct {
char **argv; /* the cli arguments of this proxy */
int conf_protocol; /* the configuration protocol version used */
+ char *proxy_uri; /* the outgoing proxy in TOR_PT_PROXY URI format */
+ unsigned int proxy_supported : 1; /* the proxy honors TOR_PT_PROXY */
+
int is_server; /* is it a server proxy? */
/* A pointer to the process handle of this managed proxy. */
@@ -112,6 +115,7 @@ STATIC int parse_smethod_line(const char *line, managed_proxy_t *mp);
STATIC int parse_version(const char *line, managed_proxy_t *mp);
STATIC void parse_env_error(const char *line);
+STATIC void parse_proxy_error(const char *line);
STATIC void handle_proxy_line(const char *line, managed_proxy_t *mp);
STATIC char *get_transport_options_for_server_proxy(const managed_proxy_t *mp);
@@ -123,6 +127,8 @@ STATIC managed_proxy_t *managed_proxy_create(const smartlist_t *transport_list,
STATIC int configure_proxy(managed_proxy_t *mp);
+STATIC char* get_pt_proxy_uri(void);
+
#endif
#endif
diff --git a/src/test/bench.c b/src/test/bench.c
index 70bac63727..825299835b 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -30,6 +30,7 @@ const char tor_git_revision[] = "";
#include "crypto_curve25519.h"
#include "onion_ntor.h"
#endif
+#include "crypto_ed25519.h"
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
static uint64_t nanostart;
@@ -79,6 +80,9 @@ perftime(void)
#define NANOCOUNT(start,end,iters) \
( ((double)((end)-(start))) / (iters) )
+#define MICROCOUNT(start,end,iters) \
+ ( NANOCOUNT((start), (end), (iters)) / 1000.0 )
+
/** Run AES performance benchmarks. */
static void
bench_aes(void)
@@ -232,6 +236,63 @@ bench_onion_ntor(void)
ntor_handshake_state_free(state);
dimap_free(keymap, NULL);
}
+
+static void
+bench_ed25519(void)
+{
+ uint64_t start, end;
+ const int iters = 1<<12;
+ int i;
+ const uint8_t msg[] = "but leaving, could not tell what they had heard";
+ ed25519_signature_t sig;
+ ed25519_keypair_t kp;
+ curve25519_keypair_t curve_kp;
+ ed25519_public_key_t pubkey_tmp;
+
+ ed25519_secret_key_generate(&kp.seckey, 0);
+ start = perftime();
+ for (i = 0; i < iters; ++i) {
+ ed25519_public_key_generate(&kp.pubkey, &kp.seckey);
+ }
+ end = perftime();
+ printf("Generate public key: %.2f usec\n",
+ MICROCOUNT(start, end, iters));
+
+ start = perftime();
+ for (i = 0; i < iters; ++i) {
+ ed25519_sign(&sig, msg, sizeof(msg), &kp);
+ }
+ end = perftime();
+ printf("Sign a short message: %.2f usec\n",
+ MICROCOUNT(start, end, iters));
+
+ start = perftime();
+ for (i = 0; i < iters; ++i) {
+ ed25519_checksig(&sig, msg, sizeof(msg), &kp.pubkey);
+ }
+ end = perftime();
+ printf("Verify signature: %.2f usec\n",
+ MICROCOUNT(start, end, iters));
+
+ curve25519_keypair_generate(&curve_kp, 0);
+ start = perftime();
+ for (i = 0; i < iters; ++i) {
+ ed25519_public_key_from_curve25519_public_key(&pubkey_tmp,
+ &curve_kp.pubkey, 1);
+ }
+ end = perftime();
+ printf("Convert public point from curve25519: %.2f usec\n",
+ MICROCOUNT(start, end, iters));
+
+ curve25519_keypair_generate(&curve_kp, 0);
+ start = perftime();
+ for (i = 0; i < iters; ++i) {
+ ed25519_public_blind(&pubkey_tmp, &kp.pubkey, msg);
+ }
+ end = perftime();
+ printf("Blind a public key: %.2f usec\n",
+ MICROCOUNT(start, end, iters));
+}
#endif
static void
@@ -514,6 +575,7 @@ static struct benchmark_t benchmarks[] = {
ENT(onion_TAP),
#ifdef CURVE25519_ENABLED
ENT(onion_ntor),
+ ENT(ed25519),
#endif
ENT(cell_aes),
ENT(cell_ops),
diff --git a/src/test/ed25519_exts_ref.py b/src/test/ed25519_exts_ref.py
new file mode 100644
index 0000000000..93dc49ee93
--- /dev/null
+++ b/src/test/ed25519_exts_ref.py
@@ -0,0 +1,234 @@
+#!/usr/bin/python
+# Copyright 2014, The Tor Project, Inc
+# See LICENSE for licensing information
+
+"""
+ Reference implementations for the ed25519 tweaks that Tor uses.
+
+ Includes self-tester and test vector generator.
+"""
+
+import slow_ed25519
+from slow_ed25519 import *
+
+import os
+import random
+import slownacl_curve25519
+import unittest
+import binascii
+import textwrap
+
+#define a synonym that doesn't look like 1
+ell = l
+
+# This replaces expmod above and makes it go a lot faster.
+slow_ed25519.expmod = pow
+
+def curve25519ToEd25519(c, sign):
+ u = decodeint(c)
+ y = ((u - 1) * inv(u + 1)) % q
+ x = xrecover(y)
+ if x & 1 != sign: x = q-x
+ return encodepoint([x,y])
+
+def blindESK(esk, param):
+ h = H("Derive temporary signing key" + param)
+ mult = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
+ s = decodeint(esk[:32])
+ s_prime = (s * mult) % ell
+ k = esk[32:]
+ assert(len(k) == 32)
+ k_prime = H("Derive temporary signing key hash input" + k)[:32]
+ return encodeint(s_prime) + k_prime
+
+def blindPK(pk, param):
+ h = H("Derive temporary signing key" + param)
+ mult = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
+ P = decodepoint(pk)
+ return encodepoint(scalarmult(P, mult))
+
+def expandSK(sk):
+ h = H(sk)
+ a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
+ k = ''.join([h[i] for i in range(b/8,b/4)])
+ assert len(k) == 32
+ return encodeint(a)+k
+
+def publickeyFromESK(h):
+ a = decodeint(h[:32])
+ A = scalarmult(B,a)
+ return encodepoint(A)
+
+def signatureWithESK(m,h,pk):
+ a = decodeint(h[:32])
+ r = Hint(''.join([h[i] for i in range(b/8,b/4)]) + m)
+ R = scalarmult(B,r)
+ S = (r + Hint(encodepoint(R) + pk + m) * a) % l
+ return encodepoint(R) + encodeint(S)
+
+def newSK():
+ return os.urandom(32)
+
+# ------------------------------------------------------------
+
+MSG = "This is extremely silly. But it is also incredibly serious business!"
+
+class SelfTest(unittest.TestCase):
+
+ def _testSignatures(self, esk, pk):
+ sig = signatureWithESK(MSG, esk, pk)
+ checkvalid(sig, MSG, pk)
+ bad = False
+ try:
+ checkvalid(sig, MSG*2, pk)
+ bad = True
+ except Exception:
+ pass
+
+ self.failIf(bad)
+
+ def testExpand(self):
+ sk = newSK()
+ pk = publickey(sk)
+ esk = expandSK(sk)
+ sig1 = signature(MSG, sk, pk)
+ sig2 = signatureWithESK(MSG, esk, pk)
+ self.assertEquals(sig1, sig2)
+
+ def testSignatures(self):
+ sk = newSK()
+ esk = expandSK(sk)
+ pk = publickeyFromESK(esk)
+ pk2 = publickey(sk)
+ self.assertEquals(pk, pk2)
+
+ self._testSignatures(esk, pk)
+
+ def testDerivation(self):
+ priv = slownacl_curve25519.Private()
+ pub = priv.get_public()
+
+ ed_pub0 = publickeyFromESK(priv.private)
+ sign = (ord(ed_pub0[31]) & 255) >> 7
+ ed_pub1 = curve25519ToEd25519(pub.public, sign)
+
+ self.assertEquals(ed_pub0, ed_pub1)
+
+ def testBlinding(self):
+ sk = newSK()
+ esk = expandSK(sk)
+ pk = publickeyFromESK(esk)
+ param = os.urandom(32)
+ besk = blindESK(esk, param)
+ bpk = blindPK(pk, param)
+ bpk2 = publickeyFromESK(besk)
+ self.assertEquals(bpk, bpk2)
+
+ self._testSignatures(besk, bpk)
+
+# ------------------------------------------------------------
+
+# From pprint.pprint([ binascii.b2a_hex(os.urandom(32)) for _ in xrange(8) ])
+RAND_INPUTS = [
+ '26c76712d89d906e6672dafa614c42e5cb1caac8c6568e4d2493087db51f0d36',
+ 'fba7a5366b5cb98c2667a18783f5cf8f4f8d1a2ce939ad22a6e685edde85128d',
+ '67e3aa7a14fac8445d15e45e38a523481a69ae35513c9e4143eb1c2196729a0e',
+ 'd51385942033a76dc17f089a59e6a5a7fe80d9c526ae8ddd8c3a506b99d3d0a6',
+ '5c8eac469bb3f1b85bc7cd893f52dc42a9ab66f1b02b5ce6a68e9b175d3bb433',
+ 'eda433d483059b6d1ff8b7cfbd0fe406bfb23722c8f3c8252629284573b61b86',
+ '4377c40431c30883c5fbd9bc92ae48d1ed8a47b81d13806beac5351739b5533d',
+ 'c6bbcce615839756aed2cc78b1de13884dd3618f48367a17597a16c1cd7a290b']
+
+# From pprint.pprint([ binascii.b2a_hex(os.urandom(32)) for _ in xrange(8) ])
+BLINDING_PARAMS = [
+ '54a513898b471d1d448a2f3c55c1de2c0ef718c447b04497eeb999ed32027823',
+ '831e9b5325b5d31b7ae6197e9c7a7baf2ec361e08248bce055908971047a2347',
+ 'ac78a1d46faf3bfbbdc5af5f053dc6dc9023ed78236bec1760dadfd0b2603760',
+ 'f9c84dc0ac31571507993df94da1b3d28684a12ad14e67d0a068aba5c53019fc',
+ 'b1fe79d1dec9bc108df69f6612c72812755751f21ecc5af99663b30be8b9081f',
+ '81f1512b63ab5fb5c1711a4ec83d379c420574aedffa8c3368e1c3989a3a0084',
+ '97f45142597c473a4b0e9a12d64561133ad9e1155fe5a9807fe6af8a93557818',
+ '3f44f6a5a92cde816635dfc12ade70539871078d2ff097278be2a555c9859cd0']
+
+PREFIX = "ED25519_"
+
+def writeArray(name, array):
+ print "static const char *{prefix}{name}[] = {{".format(
+ prefix=PREFIX,name=name)
+ for a in array:
+ h = binascii.b2a_hex(a)
+ if len(h) > 70:
+ h1 = h[:70]
+ h2 = h[70:]
+ print ' "{0}"\n "{1}",'.format(h1,h2)
+ else:
+ print ' "{0}",'.format(h)
+ print "};\n"
+
+def comment(text, initial="/**"):
+ print initial
+ print textwrap.fill(text,initial_indent=" * ",subsequent_indent=" * ")
+ print " */"
+
+def makeTestVectors():
+ comment("""Test vectors for our ed25519 implementation and related
+ functions. These were automatically generated by the
+ ed25519_exts_ref.py script.""", initial="/*")
+
+
+ comment("""Secret key seeds used as inputs for the ed25519 test vectors.
+ Randomly generated. """)
+ secretKeys = [ binascii.a2b_hex(r) for r in RAND_INPUTS ]
+ writeArray("SECRET_KEYS", secretKeys)
+
+ comment("""Secret ed25519 keys after expansion from seeds. This is how Tor
+ represents them internally.""")
+ expandedSecretKeys = [ expandSK(sk) for sk in secretKeys ]
+ writeArray("EXPANDED_SECRET_KEYS", expandedSecretKeys)
+
+ comment("""Public keys derived from the above secret keys""")
+ publicKeys = [ publickey(sk) for sk in secretKeys ]
+ writeArray("PUBLIC_KEYS", publicKeys)
+
+ comment("""The curve25519 public keys from which the ed25519 keys can be
+ derived. Used to test our 'derive ed25519 from curve25519'
+ code.""")
+ writeArray("CURVE25519_PUBLIC_KEYS",
+ (slownacl_curve25519.smult_curve25519_base(sk[:32])
+ for sk in expandedSecretKeys))
+
+ comment("""Parameters used for key blinding tests. Randomly generated.""")
+ blindingParams = [ binascii.a2b_hex(r) for r in BLINDING_PARAMS ]
+ writeArray("BLINDING_PARAMS", blindingParams)
+
+ comment("""Blinded secret keys for testing key blinding. The nth blinded
+ key corresponds to the nth secret key blidned with the nth
+ blinding parameter.""")
+ writeArray("BLINDED_SECRET_KEYS",
+ (blindESK(expandSK(sk), bp)
+ for sk,bp in zip(secretKeys,blindingParams)))
+
+ comment("""Blinded public keys for testing key blinding. The nth blinded
+ key corresponds to the nth public key blidned with the nth
+ blinding parameter.""")
+ writeArray("BLINDED_PUBLIC_KEYS",
+ (blindPK(pk, bp) for pk,bp in zip(publicKeys,blindingParams)))
+
+ comment("""Signatures of the public keys, made with their corresponding
+ secret keys.""")
+ writeArray("SELF_SIGNATURES",
+ (signature(pk, sk, pk) for pk,sk in zip(publicKeys,secretKeys)))
+
+
+
+if __name__ == '__main__':
+ import sys
+ if len(sys.argv) == 1 or sys.argv[1] not in ("SelfTest", "MakeVectors"):
+ print "You should specify one of 'SelfTest' or 'MakeVectors'"
+ sys.exit(1)
+ if sys.argv[1] == 'SelfTest':
+ unittest.main()
+ else:
+ makeTestVectors()
+
+
diff --git a/src/test/ed25519_vectors.inc b/src/test/ed25519_vectors.inc
new file mode 100644
index 0000000000..760bafb971
--- /dev/null
+++ b/src/test/ed25519_vectors.inc
@@ -0,0 +1,150 @@
+/*
+ * Test vectors for our ed25519 implementation and related
+ * functions. These were automatically generated by the
+ * ed25519_exts_ref.py script.
+ */
+/**
+ * Secret key seeds used as inputs for the ed25519 test vectors.
+ * Randomly generated.
+ */
+static const char *ED25519_SECRET_KEYS[] = {
+ "26c76712d89d906e6672dafa614c42e5cb1caac8c6568e4d2493087db51f0d36",
+ "fba7a5366b5cb98c2667a18783f5cf8f4f8d1a2ce939ad22a6e685edde85128d",
+ "67e3aa7a14fac8445d15e45e38a523481a69ae35513c9e4143eb1c2196729a0e",
+ "d51385942033a76dc17f089a59e6a5a7fe80d9c526ae8ddd8c3a506b99d3d0a6",
+ "5c8eac469bb3f1b85bc7cd893f52dc42a9ab66f1b02b5ce6a68e9b175d3bb433",
+ "eda433d483059b6d1ff8b7cfbd0fe406bfb23722c8f3c8252629284573b61b86",
+ "4377c40431c30883c5fbd9bc92ae48d1ed8a47b81d13806beac5351739b5533d",
+ "c6bbcce615839756aed2cc78b1de13884dd3618f48367a17597a16c1cd7a290b",
+};
+
+/**
+ * Secret ed25519 keys after expansion from seeds. This is how Tor
+ * represents them internally.
+ */
+static const char *ED25519_EXPANDED_SECRET_KEYS[] = {
+ "c0a4de23cc64392d85aa1da82b3defddbea946d13bb053bf8489fa9296281f495022f1"
+ "f7ec0dcf52f07d4c7965c4eaed121d5d88d0a8ff546b06116a20e97755",
+ "18a8a69a06790dac778e882f7e868baacfa12521a5c058f5194f3a729184514a2a656f"
+ "e7799c3e41f43d756da8d9cd47a061316cfe6147e23ea2f90d1ca45f30",
+ "58d84f8862d2ecfa30eb491a81c36d05b574310ea69dae18ecb57e992a896656b98218"
+ "7ee96c15bf4caeeab2d0b0ae4cd0b8d17470fc7efa98bb26428f4ef36d",
+ "50702d20b3550c6e16033db5ad4fba16436f1ecc7485be6af62b0732ceb5d173c47ccd"
+ "9d044b6ea99dd99256adcc9c62191be194e7cb1a5b58ddcec85d876a2b",
+ "7077464c864c2ed5ed21c9916dc3b3ba6256f8b742fec67658d8d233dadc8d5a7a82c3"
+ "71083cc86892c2c8782dda2a09b6baf016aec51b689183ae59ce932ff2",
+ "8883c1387a6c86fc0bd7b9f157b4e4cd83f6885bf55e2706d2235d4527a2f05311a359"
+ "5953282e436df0349e1bb313a19b3ddbf7a7b91ecce8a2c34abadb38b3",
+ "186791ac8d03a3ac8efed6ac360467edd5a3bed2d02b3be713ddd5be53b3287ee37436"
+ "e5fd7ac43794394507ad440ecfdf59c4c255f19b768a273109e06d7d8e",
+ "b003077c1e52a62308eef7950b2d532e1d4a7eea50ad22d8ac11b892851f1c40ffb9c9"
+ "ff8dcd0c6c233f665a2e176324d92416bfcfcd1f787424c0c667452d86",
+};
+
+/**
+ * Public keys derived from the above secret keys
+ */
+static const char *ED25519_PUBLIC_KEYS[] = {
+ "c2247870536a192d142d056abefca68d6193158e7c1a59c1654c954eccaff894",
+ "1519a3b15816a1aafab0b213892026ebf5c0dc232c58b21088d88cb90e9b940d",
+ "081faa81992e360ea22c06af1aba096e7a73f1c665bc8b3e4e531c46455fd1dd",
+ "73cfa1189a723aad7966137cbffa35140bb40d7e16eae4c40b79b5f0360dd65a",
+ "66c1a77104d86461b6f98f73acf3cd229c80624495d2d74d6fda1e940080a96b",
+ "d21c294db0e64cb2d8976625786ede1d9754186ae8197a64d72f68c792eecc19",
+ "c4d58b4cf85a348ff3d410dd936fa460c4f18da962c01b1963792b9dcc8a6ea6",
+ "95126f14d86494020665face03f2d42ee2b312a85bc729903eb17522954a1c4a",
+};
+
+/**
+ * The curve25519 public keys from which the ed25519 keys can be
+ * derived. Used to test our 'derive ed25519 from curve25519'
+ * code.
+ */
+static const char *ED25519_CURVE25519_PUBLIC_KEYS[] = {
+ "17ba77846e04c7ee5ca17cade774ac1884408f9701f439d4df32cbd8736c6a1f",
+ "022be2124bc1899a78ba2b4167d191af3b59cadf94f0382bc31ce183a117f161",
+ "bf4fd38ef22f718f03c0a12ba5127bd1e3afd494793753f519728b29cc577571",
+ "56c493e490261cef31633efd2461d2b896908e90459e4eecde950a895aef681d",
+ "089675a3e8ff2a7d8b2844a79269c95b7f97a4b8b5ea0cbeec669c6f2dea9b39",
+ "59e20dcb691c4a345fe86c8a79ac817e5b514d84bbf0512a842a08e43f7f087e",
+ "9e43b820b320eda35f66f122c155b2bf8e2192c468617b7115bf067d19e08369",
+ "861f33296cb57f8f01e4a5e8a7e5d5d7043a6247586ab36dea8a1a3c4403ee30",
+};
+
+/**
+ * Parameters used for key blinding tests. Randomly generated.
+ */
+static const char *ED25519_BLINDING_PARAMS[] = {
+ "54a513898b471d1d448a2f3c55c1de2c0ef718c447b04497eeb999ed32027823",
+ "831e9b5325b5d31b7ae6197e9c7a7baf2ec361e08248bce055908971047a2347",
+ "ac78a1d46faf3bfbbdc5af5f053dc6dc9023ed78236bec1760dadfd0b2603760",
+ "f9c84dc0ac31571507993df94da1b3d28684a12ad14e67d0a068aba5c53019fc",
+ "b1fe79d1dec9bc108df69f6612c72812755751f21ecc5af99663b30be8b9081f",
+ "81f1512b63ab5fb5c1711a4ec83d379c420574aedffa8c3368e1c3989a3a0084",
+ "97f45142597c473a4b0e9a12d64561133ad9e1155fe5a9807fe6af8a93557818",
+ "3f44f6a5a92cde816635dfc12ade70539871078d2ff097278be2a555c9859cd0",
+};
+
+/**
+ * Blinded secret keys for testing key blinding. The nth blinded
+ * key corresponds to the nth secret key blidned with the nth
+ * blinding parameter.
+ */
+static const char *ED25519_BLINDED_SECRET_KEYS[] = {
+ "014e83abadb2ca9a27e0ffe23920333d817729f48700e97656ec2823d694050e171d43"
+ "f24e3f53e70ec7ac280044ac77d4942dee5d6807118a59bdf3ee647e89",
+ "fad8cca0b4335847795288b1452508752b253e64e6c7c78d4a02dbbd7d46aa0eb8ceff"
+ "20dfcf53eb52b891fc078c934efbf0353af7242e7dc51bb32a093afa29",
+ "116eb0ae0a4a91763365bdf86db427b00862db448487808788cc339ac10e5e089217f5"
+ "2e92797462bd890fc274672e05c98f2c82970d640084781334aae0f940",
+ "bd1fbb0ee5acddc4adbcf5f33e95d9445f40326ce579fdd764a24483a9ccb20f509ece"
+ "e77082ce088f7c19d5a00e955eeef8df6fa41686abc1030c2d76807733",
+ "237f5345cefe8573ce9fa7e216381a1172796c9e3f70668ab503b1352952530fb57b95"
+ "a440570659a440a3e4771465022a8e67af86bdf2d0990c54e7bb87ff9a",
+ "ba8ff23bc4ad2b739e1ccffc9fbc7837053ea81cdfdb15073f56411cfbae1d0ec492fc"
+ "87d5ec2a1b185ca5a40541fdef0b1e128fd5c2380c888bfa924711bcab",
+ "0fa68f969de038c7a90a4a74ee6167c77582006f2dedecc1956501ba6b6fb10391b476"
+ "8f8e556d78f4bdcb9a13b6f6066fe81d3134ae965dc48cd0785b3af2b8",
+ "deaa3456d1c21944d5dcd361a646858c6cf9336b0a6851d925717eb1ae186902053d9c"
+ "00c81e1331c06ab50087be8cfc7dc11691b132614474f1aa9c2503cccd",
+};
+
+/**
+ * Blinded public keys for testing key blinding. The nth blinded
+ * key corresponds to the nth public key blidned with the nth
+ * blinding parameter.
+ */
+static const char *ED25519_BLINDED_PUBLIC_KEYS[] = {
+ "722d6da6348e618967ef782e71061e27163a8b35f21856475d9d2023f65b6495",
+ "1dffa0586da6cbfcff2024eedf4fc6c818242d9a82dbbe635d6da1b975a1160d",
+ "5ed81f98fed5a6acda4ea6da2c34fab0ab359d950c510c256473f1f33ff438b4",
+ "6e6f92a54fb282120c46d9603df41135f025bc1f58f283809d04be96aeb04040",
+ "cda236f28edc4c7e02d18007b8dab49d669265b0f7aefb1824d7cc8e73a2cd63",
+ "367b03b17b67ca7329b89a520bdab91782402a41cd67264e34b5541a4b3f875b",
+ "8d486b03ac4e3b486b7a1d563706c7fdac75aee789a7cf6f22789eedeff61a31",
+ "9f297ff0aa2ceda91c5ab1b6446f12533d145940de6d850dc323417afde0cb78",
+};
+
+/**
+ * Signatures of the public keys, made with their corresponding
+ * secret keys.
+ */
+static const char *ED25519_SELF_SIGNATURES[] = {
+ "d23188eac3773a316d46006fa59c095060be8b1a23582a0dd99002a82a0662bd246d84"
+ "49e172e04c5f46ac0d1404cebe4aabd8a75a1457aa06cae41f3334f104",
+ "3a785ac1201c97ee5f6f0d99323960d5f264c7825e61aa7cc81262f15bef75eb4fa572"
+ "3add9b9d45b12311b6d403eb3ac79ff8e4e631fc3cd51e4ad2185b200b",
+ "cf431fd0416bfbd20c9d95ef9b723e2acddffb33900edc72195dea95965d52d888d30b"
+ "7b8a677c0bd8ae1417b1e1a0ec6700deadd5d8b54b6689275e04a04509",
+ "2375380cd72d1a6c642aeddff862be8a5804b916acb72c02d9ed052c1561881aa658a5"
+ "af856fcd6d43113e42f698cd6687c99efeef7f2ce045824440d26c5d00",
+ "2385a472f599ca965bbe4d610e391cdeabeba9c336694b0d6249e551458280be122c24"
+ "41dd9746a81bbfb9cd619364bab0df37ff4ceb7aefd24469c39d3bc508",
+ "e500cd0b8cfff35442f88008d894f3a2fa26ef7d3a0ca5714ae0d3e2d40caae58ba7cd"
+ "f69dd126994dad6be536fcda846d89dd8138d1683cc144c8853dce7607",
+ "d187b9e334b0050154de10bf69b3e4208a584e1a65015ec28b14bcc252cf84b8baa9c9"
+ "4867daa60f2a82d09ba9652d41e8dde292b624afc8d2c26441b95e3c0e",
+ "815213640a643d198bd056e02bba74e1c8d2d931643e84497adf3347eb485079c9afe0"
+ "afce9284cdc084946b561abbb214f1304ca11228ff82702185cf28f60d",
+};
+
diff --git a/src/test/example_extrainfo.inc b/src/test/example_extrainfo.inc
new file mode 100644
index 0000000000..606279a765
--- /dev/null
+++ b/src/test/example_extrainfo.inc
@@ -0,0 +1,192 @@
+static const char EX_EI_MINIMAL[] =
+ "extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
+ "published 2014-10-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
+ "V3l9u1uUdGiUPOl8j+hRNw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
+ "zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_MINIMAL_FP[] = "3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B";
+static const char EX_EI_MINIMAL_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALSppIF3t3wOAm4fzxRvK+q/wh1gGAWwS0JEn8d+c/x+rt1oQabGkqsB\n"
+ "GU6rz1z1AN02W0P2+EcyJQVBjGR3gHQNoDGx0KIdnr3caGAw3XmQXrJLPaViEk28\n"
+ "RJMxx6umpP27YKSyEMHgVTDXblKImT0mE7fVOx8tD0EWRYazmp4NAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char EX_EI_MAXIMAL[] =
+ "extra-info bob FF8248FE780A7236D3FA5D62DEA642055135F942\n"
+ "published 2014-10-05 20:07:00\n"
+ "opt foobarbaz\n"
+ "read-history 900 1,2,3\n"
+ "write-history 900 1,2,3\n"
+ "dirreq-v2-ips 1\n"
+ "dirreq-v3-ips 100\n"
+ "dirreq-v3-reqs blahblah\n"
+ "dirreq-v2-share blahblah\n"
+ "dirreq-v3-share blahblah\n"
+ "dirreq-v2-resp djfkdj\n"
+ "dirreq-v3-resp djfkdj\n"
+ "dirreq-v2-direct-dl djfkdj\n"
+ "dirreq-v3-direct-dl djfkdj\n"
+ "dirreq-v2-tunneled-dl djfkdj\n"
+ "dirreq-v3-tunneled-dl djfkdj\n"
+ "dirreq-stats-end foobar\n"
+ "entry-ips jfsdfds\n"
+ "entry-stats-end ksdflkjfdkf\n"
+ "cell-stats-end FOO\n"
+ "cell-processed-cells FOO\n"
+ "cell-queued-cells FOO\n"
+ "cell-time-in-queue FOO\n"
+ "cell-circuits-per-decile FOO\n"
+ "exit-stats-end FOO\n"
+ "exit-kibibytes-written FOO\n"
+ "exit-kibibytes-read FOO\n"
+ "exit-streams-opened FOO\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "ZO79bLlWVNIruCnWW9duDcOKydPWbL5DfrpUv5IRLF4MMFoacMUdJPDUs9e+wY2C\n"
+ "zndHe6i2JK7yKJj+uCOSC8cx61OLG+kVxMLJ/qhA4H5thrYb+GpzMKwbHzQc3PTH\n"
+ "zHRzj041iWXTL7/DMaQlpJOBoac/wTSIKzoV2B00jBw=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_MAXIMAL_FP[] = "FF8248FE780A7236D3FA5D62DEA642055135F942";
+static const char EX_EI_MAXIMAL_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANSpkYhHUW1EqodY4d3JRbvEM1vjjR/vEE8gjONiJ5t2Sten53jzt8bh\n"
+ "8/VJn7pQGs8zR5CIxCw4P68xMtZJJedS3hhjqubheOE/yW1DtpkiCf+zVEaLpeA8\n"
+ "fYQChkRICnR/BZd4W9bbohLVII5ym2PaJt2ihB3FeVZIsGXm4wxhAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char EX_EI_BAD_SIG1[] =
+ "extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
+ "published 2014-10-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
+ "V3l9u1uUdGiUPOl8j+hXXw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
+ "zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_SIG2[] =
+ "extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
+ "published 2014-10-06 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
+ "V3l9u1uUdGiUPOl8j+hRNw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
+ "zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_SIG3[] =
+ "extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
+ "published 2014-10-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
+ "V3l9u1uUdGiUPOl8j+hRNw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
+ "zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_FP[] =
+ "extra-info bob C34293303F0F1E42CB14E593717B834E8E53797D8888\n"
+ "published 2014-10-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "IDA8ryUYeMx7+Au/xQmX7Y8fXksoHUOXmePND2JYM4rPfishQJ1LpQ15KrolOZDH\n"
+ "FVIk3RmCefNlJeS1/UgWPcU8u2nGw1YQuRBHF4ViTmZ0OevI1pTsSApl4+oIx2dy\n"
+ "DGgCQmKfMbaOixIK8Ioh1Z2NUfMkjbUUE2WWgFTAsac=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_FP_FP[] = "C34293303F0F1E42CB14E593717B834E8E53797D";
+static const char EX_EI_BAD_FP_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKXMSbif4fG+BW/5lIq5V1tMRondIUfKiNizp0E6EcBw5LvYfQV6zrj8\n"
+ "HmMFbB/WGf9XGVMxIBzxzeQBRvCQJh+0QH7+ju5/isIHJZsACMILepr6ywmCcjVU\n"
+ "iYRtC8zGQLqfkf2cNoo7AhcI5i/YzyW2u1zmbPX5J+8sUErfxydbAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char EX_EI_BAD_NICKNAME[] =
+ "extra-info bobhasaverylongnameandidontthinkweshouldlethim A4EA2389A52459B3F7C7121A46012F098BDFC2A4\n"
+ "published 2014-10-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "e2wLJFThRMGawxKrQPuH2XCLek/LJsg4XOB8waAjE0xdHOrzjur9x1jIxy7DVU6t\n"
+ "z1edbIoL24qucMJvFy2xjSQhFRX4OsyNc0nWr3LfJnTW9aEmxuwXM+mltUD2uFN1\n"
+ "2vYOIQjUmJwS2yfeSKnhXEl2PWVUmgzYL3r4S5kHco4=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_NICKNAME_FP[] = "A4EA2389A52459B3F7C7121A46012F098BDFC2A4";
+static const char EX_EI_BAD_NICKNAME_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKfq7oxD1kMu1+zeG2UVXN4vOu6FDp0V/olA3ttmXpUCgCiBxWTgtwNl\n"
+ "nPf0HcKMaCp/0D9XrbhvIoOsg0OTf1TcJfGsA/zPG7jrWYa4xhD50KYvty9EINK9\n"
+ "/UBWNSyXCFDMqnddb/LZ8+VgttmxfYkpeRzSSmDijN3RbOvYJhhBAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+const char EX_EI_BAD_TOKENS[] =
+ "extra-info bob 6F314FB01A31162BD5E473D4977AC570DC5B86BB\n"
+ "published 2014-10-05 20:07:00\n"
+ "published 2014-10-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "lhRIafrkKoQmnUoBLiq4XC8XKXrleGJZ5vefkLcgjOJ5IffsvVdIA7Vqq/ISbPrG\n"
+ "b/Zs0sJNL6naHPxJBglgHJqksSyiYHaeOetXg2Rb+vZ1v2S5BrVgk1nPMDhyIzqc\n"
+ "zU7eCxFf/1sXKtWlEKxGdX4LmVfnIln5aI31Bc4xRrE=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+const char EX_EI_BAD_TOKENS_FP[] = "6F314FB01A31162BD5E473D4977AC570DC5B86BB";
+const char EX_EI_BAD_TOKENS_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAL7Z8tz45Tb4tnEFS2sAyjubBV/giSfZdmXRkDV8Jo4xqWqhWFJn7+zN\n"
+ "AXBWBThGeVH2WXrpz5seNJXgZJPxMTMsrnSCGcRXZw0Npti2MkLuQ6+prZa+OPwE\n"
+ "OyC6jivtAaY/o9iYQjDC2avLXD3N4LvoygyF418KnNcjbzuFygffAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char EX_EI_BAD_START[] =
+ "published 2014-10-05 20:07:00\n"
+ "extra-info bob 5CCCACE71A9BDB5E8E0C942AB3407452350434C0\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "BOiWgexqCAMZ8uyJ7jwBwRkz7Ox8cT4BImkmkV3bQiZgcWvPiYA3EnCm2ye48Ldg\n"
+ "zBST2p6zJM5o4MEDYGMxfViS86Abj/z7DOY1gtLhjmAaVjIIpXc3koxEZtzCecqy\n"
+ "JQz6xEg9/KoEuoT0DRrfYQ+KtQfzBDWrotfOvEa1rvc=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_START_FP[] = "5CCCACE71A9BDB5E8E0C942AB3407452350434C0";
+static const char EX_EI_BAD_START_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAK2OCIfM6Cin/lq99Z3w9tl6HeyGlkBZu9MQEPHxqGIHTq78lIC1UkrC\n"
+ "6NTqlrHBV9dmfzdwJn4GgMWsCZafL0FPIH3HNyNKUxLgyjixyKljHx2rfErSfOxI\n"
+ "bMoOGBKv7m1EZZ0O5uG9ly9MBiNGdJyLdlnVvH7wSCnYciizpO4lAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char EX_EI_BAD_PUBLISHED[] =
+ "extra-info bob E67C477E3536BDE348BD407426D9679E5AE0BC16\n"
+ "published 2014-99-05 20:07:00\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "l45IziBaXRKIjPAIUogMFNjQgH6k6Vm0+6r5+oByr4sP+B3ufNdUA6+WqBs43F0Z\n"
+ "IqcJiT9nFn0DuNd/liOyOCixppDLx5h5NrhoGqcT3ySADEEXhzjlmc35TI3YBNVO\n"
+ "v98fotmwIEg9YRWVGPg6XuIn2PRyiboFyjUpaYGCV0Q=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_EI_BAD_PUBLISHED_FP[] = "E67C477E3536BDE348BD407426D9679E5AE0BC16";
+static const char EX_EI_BAD_PUBLISHED_KEY[] =
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAL7q8GEI18iv8Fo0QbNHmFatQ2FNacalPldpmKUdMJYEVZtdOR0nhcrY\n"
+ "BvG6303md3INygg+KP49RvWEJR/cU4RZ9QfHpORxH2OocMyRedw2rLex2E7jNNSi\n"
+ "52yd1sHFYI8ZQ4aff+ZHUjJUGKRyqpbc8okVbq/Rl7vug0dd12eHAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
diff --git a/src/test/failing_routerdescs.inc b/src/test/failing_routerdescs.inc
new file mode 100644
index 0000000000..b49d59fd8a
--- /dev/null
+++ b/src/test/failing_routerdescs.inc
@@ -0,0 +1,668 @@
+/* This one actually succeeds */
+static const char EX_RI_MINIMAL[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAObzT4opT9uaThByupbb96tYxVpGxzL9CRPKUcU0beGpHyognD9USHWc\n"
+ "SpSpKfBL5P3xr2i/XTs34M4UTbT9PE7bVyxv7RD/BZmI4gc8R3PMU77xxbpEU5bK\n"
+ "LF3QUPpuB88m/2fXUGgMNVDc5MIq6pod2NRoDpeU7WA8T3ewXzK5AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM1QKsQiup9DNMCgNeE2FkAhCWzpMZKCn1nNlZbDGfE3Z22ex6bdWWY6\n"
+ "ocEZ3JZDsZsnaZrdYxrL3Mquq7MbHdfx90EdlOvDRP1SAIbZ55mLR77fZTu4BKd/\n"
+ "h9BC6I26uZE0QavFq3+BhoVVhVn5Mqv05nR9CeUMSSZLxw/RJm4DAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Ft/y3JXowjItgfTHwYcZzuUgXrskluoINW5sr+GQoNYE2F4sT8o0tBBJwqJ6FwKd\n"
+ "fkIprv9UXqkv5iY+pXSYSI12mY1K5GMNkXiObk46NjuoNNP9l8oidhO6eNfcE+k3\n"
+ "CRIYS4FbBaD0fWUSwgMuo0Bp83/Wzp3B9ytEBh0/624=\n"
+ "-----END SIGNATURE-----\n";
+
+/* So does this, and it's bigger. */
+static const char EX_RI_MAXIMAL[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANNI56H+b7SW5LMzvXyY5NJzXszsHZZ4O1CPm4CePhBsAz1r0s1JYJ1F\n"
+ "Anrc0mEcLtmj0c5+HnhPBNrfpjO6G94Wp3NZMVykHDhfNVDBRyFZMroG8/GlysYB\n"
+ "MQPGQYR0xBgiuclNHoyk/vygQhZekumamu2O86EIPcfg9LhGIgEbAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALvuNVSmg6R9USFbQcNbRjMCJAV0Rwdv0DlS6Rl02ibJgb01G7v391xE\n"
+ "d9Njzgf93n8gOrE195bkUbvS6k/DM3HFGgArq6q9AZ2LTbu3KbAYy1YPsSIh07kB\n"
+ "/8kkvRRGx37X9WGZU3j5VUEuzqI//xDE9lbanlnnFXpnb6ymehDJAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject 127.0.0.1:*\n"
+ "accept *:80\n"
+ "reject *:*\n"
+ "ipv6-policy accept 80,100,101\n"
+ "ntor-onion-key s7rSohmz9SXn8WWh1EefTHIsWePthsEntQi0WL+ScVw\n"
+ "uptime 1000\n"
+ "hibernating 0\n"
+ "unrecognized-keywords are just dandy in this format\n"
+ "platform Tor 0.2.4.23 on a Banana PC Jr 6000 Series\n"
+ "contact O.W.Jones\n"
+ "fingerprint CC43 DC8E 8C9E 3E6D 59CD 0399 2491 0C8C E1E4 50D2\n"
+ "read-history 900 1,2,3,4\n"
+ "write-history 900 1,2,3,4\n"
+ "extra-info-digest AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
+ "hidden-service-dir\n"
+ "allow-single-hop-exits\n"
+ "family $AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA $BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n"
+ "caches-extra-info\n"
+ "or-address [::1:2:3:4]:9999\n"
+ "or-address 127.0.0.99:10000\n"
+ "opt fred is a fine router\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "x5cxL2h2UsEKk2OVnCTxOF8a89HAe/HwQnSlrBy8+l0YdVCcePDJhm1WyWU7ToHZ\n"
+ "K8auwreuw+u/n14sQHPYrM9NQE689hP4LC9AYOnrCnMHysfVqKuou+DSKYYRgs0D\n"
+ "ySCmJ9p+xekfmms+JBmS5o5DVo48VGlG0VksegoB264=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+/* I've messed with 12 bits of the signature on this one */
+static const char EX_RI_BAD_SIG1[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAObzT4opT9uaThByupbb96tYxVpGxzL9CRPKUcU0beGpHyognD9USHWc\n"
+ "SpSpKfBL5P3xr2i/XTs34M4UTbT9PE7bVyxv7RD/BZmI4gc8R3PMU77xxbpEU5bK\n"
+ "LF3QUPpuB88m/2fXUGgMNVDc5MIq6pod2NRoDpeU7WA8T3ewXzK5AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM1QKsQiup9DNMCgNeE2FkAhCWzpMZKCn1nNlZbDGfE3Z22ex6bdWWY6\n"
+ "ocEZ3JZDsZsnaZrdYxrL3Mquq7MbHdfx90EdlOvDRP1SAIbZ55mLR77fZTu4BKd/\n"
+ "h9BC6I26uZE0QavFq3+BhoVVhVn5Mqv05nR9CeUMSSZLxw/RJm4DAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Ft/y3JXowjItgfTHwYcZzuUgXrskluoINW5sr+GQoNYE2F4sT8o0tBBJwqJ6FwKd\n"
+ "fkIprv9UXqkv5iY+pXSYXX12mY1K5GMNkXiObk46NjuoNNP9l8oidhO6eNfcE+k3\n"
+ "CRIYS4FbBaD0fWUSwgMuo0Bp83/Wzp3B9ytEBh0/624=\n"
+ "-----END SIGNATURE-----\n";
+
+/* This is a good signature of the wrong data: I changed 'published' */
+static const char EX_RI_BAD_SIG2[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAObzT4opT9uaThByupbb96tYxVpGxzL9CRPKUcU0beGpHyognD9USHWc\n"
+ "SpSpKfBL5P3xr2i/XTs34M4UTbT9PE7bVyxv7RD/BZmI4gc8R3PMU77xxbpEU5bK\n"
+ "LF3QUPpuB88m/2fXUGgMNVDc5MIq6pod2NRoDpeU7WA8T3ewXzK5AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM1QKsQiup9DNMCgNeE2FkAhCWzpMZKCn1nNlZbDGfE3Z22ex6bdWWY6\n"
+ "ocEZ3JZDsZsnaZrdYxrL3Mquq7MbHdfx90EdlOvDRP1SAIbZ55mLR77fZTu4BKd/\n"
+ "h9BC6I26uZE0QavFq3+BhoVVhVn5Mqv05nR9CeUMSSZLxw/RJm4DAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:01\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Ft/y3JXowjItgfTHwYcZzuUgXrskluoINW5sr+GQoNYE2F4sT8o0tBBJwqJ6FwKd\n"
+ "fkIprv9UXqkv5iY+pXSYSI12mY1K5GMNkXiObk46NjuoNNP9l8oidhO6eNfcE+k3\n"
+ "CRIYS4FbBaD0fWUSwgMuo0Bp83/Wzp3B9ytEBh0/624=\n"
+ "-----END SIGNATURE-----\n";
+
+/* This one will fail while tokenizing the first line. */
+static const char EX_RI_BAD_TOKENS[] =
+ "router bob\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANGCgvZc+JRtAzuzk3gBD2rH9SHrXzjJ1wqdU3tLKr7FamKCMI2pLwSA\n"
+ "FZUpTuSqB9wJ/iVcYws+/kA3FjLqgPtzJFI0SVLvQcz5oIC1rEWpuP6t88duMlO9\n"
+ "flOUzmYu29sBffrXkQr8pesYvakyXArOJVeRR7fSvouneV5aDYWrAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAML+pYZoYc+whKLijupd63xn0gzlEQqe7k07x/lWMqWFT37FfG6YeNr5\n"
+ "fpFoo77FDfuFaL+VfPfI8i88g157hcPKBVX6OyRH54+l5By0tN91S0H+abXjXQpv\n"
+ "U/Bvmul+5QpUeVJa1nPg71HRIauoDnBNexUQ7Xf/Bwb2xCt+IJ6DAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "tbxtYYzyVqi6w6jz1k8NPjFvZaSNR0WzixVTTvKKGoMPx/6+Z8QAFK1ILzRUVucB\n"
+ "nRhmZMFaPr3vREMErLRE47ODAzwoBCE9C+vYFvROhgfzuQ3cYXla+4sMaRXYZzjH\n"
+ "PQ82bTwvSbHsR8fTTgePD/Ac082WxXTGpx6HOLBfNsQ=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_RI_BAD_PUBLISHED[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMoipSwZgTG6SpSOm6ENbyALS1Ljqqa1LSGmtHSRfGYgUQGWZXERXKQj\n"
+ "P5ql6o7EbGr1wnispGW/KB8Age09jGDvd/oGhQ9TDFluhLZon3obkZSFw7f9iA7Q\n"
+ "s29rNxoeXXLZVyS7+sux70b8x2Dt4CeG8GA8nQLljy1euwU+qYYJAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAPzfzQ+2WFMUvnB3z0xD+zwczWcFyYYNW8Lj7/aRGSNN2DICp5uzSjKq\n"
+ "qkYQ+C8jG21+MR2PE+ZBmq6CL5mvlFKlWKouXUlN7BejwWf2gw0UYag0SYctae1b\n"
+ "bu8NuUEvdeGWg5Odgs+abH7U9S0hEtjKrmE5vvJS5L841IcaPLCFAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 99:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "G92pnwCIXGJ9Q0fI9y4m/fHpWCsD0Hnk81/6T4TmRH3jt77fc0uRdomUOC5id4kz\n"
+ "J2M4vqXwRs5OK+eaPbtxf8Yv6FPmB3OBNCIhwNHIIqzKQStHUhPxD3P6j8uJFwot\n"
+ "/CNGciDN+owZ2DzwrXpszDfzcyp/nmwhApbi3W601vY=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+/* Bandwidth field isn't an integer. */
+static const char EX_RI_BAD_BANDWIDTH[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAN32LAvXQaq0p554FcL4LVwnxyiZvscfuFnfpXwWTDRJJHd2+JCttWIx\n"
+ "v+eW7dNq+rq/tzSzaZwnp8b4V2skLRojSt6UUHD234eZcsPwUNhSr0y1eMuoZbnV\n"
+ "UBBPevpuXea85aSFEXXRlIpQfvFc43y3/UFoRzo5iMPqReo2uQ4BAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMBuF1GvOyVcRDNjzlEmGHJkTA7qkaWgTp33NSY/DPEJoahg0Qswuh2w\n"
+ "1YCBqem6Txp+/Vl9hoUoUGwb7Vwq0+YDMSyr0z3Ih2NcNjOMZPVtjJuv+3wXrQC8\n"
+ "LPpCpfU9m9QvhQ7f9zprEqUHOQTT0v5j2a5bpfd++6LFxrMUNwbfAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth hello world today\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "svABTGDNJOgaiPLqDlkRU6ldYJcoEe2qHlr4O30lVM2hS3Gg6o4QARL7QRt7VepT\n"
+ "SruR6pE83xOr7/5Ijq5PlamS4WtODMJSH3DXT2hM5dYYrEX5jsJNZTQ+cYwPQI3y\n"
+ "ykuvQIutH6ipz5MYc9n0GWAzDjLq1G8wlcEfFXQLD10=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+/* Onion key is actually a signature. */
+static const char EX_RI_BAD_ONIONKEY1[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANByIdFOKA3r2nnWyLjdZE8oGHqJE62T1zjW/nsCzCJQ8/kBMRYeGDu4\n"
+ "SeUJJ2rsh2t3PNzkqJM14f4DKmc2q76STsOW0Zcj70Bjhxb9r/OfyELVsi+x3CsE\n"
+ "Zo/W4JtdlVFjqevhODJdyFNLKOvqwG7sZo/K++Hx01Iu0zXLeg8nAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "svABTGDNJOgaiPLqDlkRU6ldYJcoEe2qHlr4O30lVM2hS3Gg6o4QARL7QRt7VepT\n"
+ "SruR6pE83xOr7/5Ijq5PlamS4WtODMJSH3DXT2hM5dYYrEX5jsJNZTQ+cYwPQI3y\n"
+ "ykuvQIutH6ipz5MYc9n0GWAzDjLq1G8wlcEfFXQLD10=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Cc/Y22KFvxXPXZtjvGIyQdjm4EMhXVXJEBwt8PvK7qlO1AgiVjEBPkUrTQQ/paLQ\n"
+ "lmeCN6jEVcZ8lNiVZgzRQ/2mTO3xLBPj26UNSDuouUwZ01tZ4wPENylNYnLKv5hg\n"
+ "gYARg/nXEJiTVe9LHl99Hr9EWWruRG2wFQjjTILaWzI=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+/* Onion key has exponent 3 */
+static const char EX_RI_BAD_ONIONKEY2[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKP1kWHsH/BZhNSZmn0FyzIrAHtMl1IVPzc7ABbx+kK+IIEMD9k1fy2h\n"
+ "AP2JTm2UmJDUwutVxPsxmndI+9QsRDpu33E5Ai4U1Rb6Qu+2BRj43YAyg414caIu\n"
+ "J5LLn6bOzt7gtz0+q69WHbnwgI4zUgUbwYpwoB7k0dRY97xip9fHAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGHAoGBANBKlyoqApWzG7UzmXcxhXM4T370FbN1edPbw4WAczBDXJslXCU9Xk1r\n"
+ "fKfoi/+WiTGvH7RcZWPm7wnThq2u2EAO/IPPcLE9cshLBkK28EvDg5K/WsYedbY9\n"
+ "1Gou+7ZSwMEPv2b13c7eWnSW1YvFa64pVDKu2sKnIjX6Bm0HZGbXAgED\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "cYcBOlapA+R4xq3nn5CjpnzNXdDArMlHuXv4MairjleF1n755ecH8A/R8YIc2ioV\n"
+ "n/C1TACzFVQ12Q9P3iikVOjIXNxYzaz4Lm/L/Lq4sEOPRJC38QEXeIHEaeM51lE6\n"
+ "p6kCqXcGu/51p5vAFCSiXI1ciucmx93N+TH1yGKRLV0=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_RI_BAD_PORTS[] =
+ "router fred 127.0.0.1 900001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANVi/MVWhzT5uo3Jxw4ElS7UGmA24dnckdkCLetMhZOcE9e9mg4WcImL\n"
+ "NuBe2L/9YaL4PFVchCGlq73phKG6yFdqJdjDV8Qh9MJdAYWW2ORrjRvCrspPaYPN\n"
+ "BGJrkD2Gd4u3sq7f26TIkzmBx0Acd/FD4PQf8+XOt9YYd36ooS4vAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALtP4cIpAYp9nqo1ak4SxALcndFw4o51U36R4oa+uJS/lYQPHkMMOj6K\n"
+ "+AVnj9sxkDJ1POaU5lsCQ5JPG1t+Tkh7vDlJb6RCUy25vJOuaQCb9GVVY7KQTJqA\n"
+ "E0fU73JdKACNjMlbF36aliQhrG4Fq2Uv+y7yp8qsRxQ8jvzEMES/AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "xzu2T+pMZtdsS5q1cwXM2hMIH2c8mpAV31G2hKIuiQRwtPD1ne4iJsnoVCXhFakd\n"
+ "QTq7eTXM174fGWyIT93wvQx/Uqnp29dGZp/VaNOsxHFdYVB4VIVqkBh757h+PSJ+\n"
+ "VNV5JUm4XQ1QbmniJGdTQp4PLBM++fOXMR3ZNd6rt4o=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_NEG_BANDWIDTH[] =
+ "router fred 100.127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMCG/ZCXNCF02uXRSCP7qWBN75jDMQZ363ubnQWhF9KDDNWWiwj3UiZR\n"
+ "zqsM4zKRgjtarWZvp2qxKABFAODd+j9iq5DvUGRbbXv+aR8TT/ifMtwwxHZQBk1F\n"
+ "1hbsLdwWzGIiyz5k2MVhXnt6JTlklH2hgT++gt9YTHYKxkssaq5TAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM3vk/4kOTB1VXrve29JeHOzNUsPwKruBcjxJf+aatxjf6KO2/RW41bM\n"
+ "gRYq9V7VAYeZTsbS727fy03F5rk3QIBhMJxm9FHatQ6rT/iEDD4Q1UZQsNtm+OLf\n"
+ "/TkZZhgfB3MiDQ4ld/+GKd7qww8HXTE+m/g1rXNyZPKozn8K7YUHAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 -1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "bUBBZYZWqCbsH4/7fNXtC/HgIZNGOfDF9v4d9YfKaDs5xDYf2o67hRcwx5imhrgC\n"
+ "IU7n9AI4AGxkFoN6g3Y/t4pqebxdkF678rRDCtrlwwreAiUktgrwnetp9Tpo16xj\n"
+ "V7Uf6LcqQdvu78lRh1dsrY78sf7sb90vusFMPLXGUKM=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_IP[] =
+ "router fred 100.127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMtMrM24AJpJCevxnseIpRlSuAIMksfkfky2+noe7Rok8xn6AMQzMrwx\n"
+ "AiCJ8Jy4DBzIKUiJK4/y1FimyM08qZGR0xeqblCxZ1lbSiXv6OYxoaD2xmWw8zEP\n"
+ "Zgu4jKReHh+gan1D+XpAbFNY0KrANhjRo96ZZ3AQsZQcWBiPKCynAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAOPclmBO/amw1RWTSI1y80qY/EPjc0I+sk9HKr0BQOovxqJ0lmy9Gaue\n"
+ "y+MOejQ9H2hNev0nd7z1fPxEogt7SCe22qJHHX3xDf+D9RpKsvVzDYZsk7hVL7T1\n"
+ "mwHzuiV/dtRa7yAMp7+q0vTUGesU2PYFYMOyPvz5skNLSWrXOm05AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "g6besL/zxOp0N6Q5/7QZgai2kmCU5EAWJlvZrf5jyrjKhsv2a4LDkap07m9QRFqW\n"
+ "GGe7g5iiABIqnl0kzv7NLX7ah+d/xxv+IILXyZfVTxSw0e+zFb3uPlQ7f9JsGJ8i\n"
+ "a+w8wyyDBpOAmi8Ny866Cnp9ojVzCyIErUYHFaPvKao=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_RI_BAD_DIRPORT[] =
+ "router fred 127.0.0.1 9001 0 bob\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANKcD6DJ16X3yvdq05jatdwgjO+hyoIpckW9sV/OkdfIZwf+S6Q4pZGC\n"
+ "doMw5XeOM52gjpx42kUp6M2WlTGDFEpaNU0VyeZYG/M1CM1xvfj3+1PoebioAGdf\n"
+ "GuhNBCHZdaYNiOGnh9t2GgUomgpE6njdS/lovSrDeTL469hfcUghAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANWeGHig5wE9UijaNnEW5au3B3hZKSlzCi+T6MYDPbbYhm8qJaVoXUXF\n"
+ "EP1EUgzDcX3dPEo9upUA1+91GkjGQCo9eOYlqGib8kHIwKnHZK+hernBc/DnOeUp\n"
+ "Wyk9SW5s+fi12OQhr3NGjbSn76FMY9XU3Qt7m3EviTwWpI3Jr5eRAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "t77wEoLjyfMf9LKgBfjveosgwvJ8Go0nb27Ae3Ng9tGtR4qaJQfmwZ5fOOuVU9QC\n"
+ "3s8ww3aY91KD3NTcN3v3FKngxWtRM8AIfwh4pqT3zW6OSP4+nO3xml7ql0Zf6wfj\n"
+ "TPFV2941O3yplAsmBJ41sRSWizF04wTtZAIgzY7dMLA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_NAME2[] =
+ "router verylongnamethatnevereverendsandgoesontoolong 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAL0mcUxg7GJ6oxgciLiBCbo+NuZ/OVKRrERCSM6j6iHERcB9+ciSRgQ5\n"
+ "H6o6FUX2LoRmHYzBk1x7kIjHa9kx9g6CAbBamdZrQbdVnc1y2NrdHB/jvwLj3C48\n"
+ "PgzFIrLg9OlkuoWck/E+YpPllONfF65e0+ualgVjPgpQpXwmz+ktAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAOgHvvTAxyjJtHx9W2X7aOI05H9sYDDY+sxhovT/8EpAHrioex54tsMT\n"
+ "ifgtoXTjGIBEOTDi/1ry39nEW5WPbowqvyzRfR2M43pc96WV7e1nhmD/JrnTYgtR\n"
+ "5/15KxcMJxoDhod7WZ/wlXBnHc2VevX8JTaeOe9KYORCj5iNbtVZAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "j/nFT5gyj20cLHWv94O1jmnqy3n6qkO8Av0OdvvfNeXsMK2UHxk84vzFvEwpUF/Y\n"
+ "i+VR3LXY4CjTpuliMtjt7BQGtmJSvB8W0CeIUenIGzfwDxW9dG2o7spDldKDB/OU\n"
+ "C1wyHvKaA6Yss/02RIDa4AxyjsfbgdJ91qK+aAnYAtA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_BANDWIDTH2[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALQDCm9VEopiYILmt4X9kP6DQazfgKnLXv+6rHbc4qtmvQQD3TVYbxMP\n"
+ "F4sEUaz+YHAPnomfDVW3a0YFRYXwDzUm1n47YYCyhUzEaD2f69Mcl/gLpKdg+QOy\n"
+ "boGB1oD4CStWL3y05KhxxTNiTrg+veMzXTqNwryCYm+GoihIAM9fAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALYHwdx6bmYy09AW5ElN/DWh0fHh3mBK97ryiIMi8FImYfzbw2BR6xuT\n"
+ "aQT5omqS3PNJJcNWZt5gOyDtA9kLh03cch7t1PenXSYJshbME2bDrZDJKVJMN6vV\n"
+ "B1v/9HjXsVF50jBzZsJo3j26XCPT5s6u9wqUFWW09QR3E/1HInHVAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 -1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "p09ijyuvcW+WKRj4mJA/nkLCvZkRcMzykAWheJi1IHCoqhXFdkFLiIRqjaeDVHRr\n"
+ "zBtD+YCQiGvFcaQJ9IUhh7IleHcyyljmDYlvuBAxWiKvVZstJac0kclCU4W+g8yK\n"
+ "0Qug3PmGKk115x2TllHaCZqMo5OkK4I/WAsKp+DnJ1A=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_UPTIME[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMM0Nubr1VXQ/FcgIQTFxZpZDlAEh2XN8FoJ8d+X5S46VDGijmMoYmyN\n"
+ "oLXqMTGmOaR0RGZOeGLgDzeY8tLrfF821IjfkXeAANZibUjdsHwqHO3wlWD2v+GN\n"
+ "0GBocWXEdAp/os229mQQKgYAATJ0Ib3jKhBdtgm5R444u8VX5XnbAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMpyOr4kEtSTZw4H9eSkH2+WmwIlO4VBpY2HkPS00l6L5fM2REjt50Xi\n"
+ "lsNOz8Q6mAn5cMYmsGlv61kg01mCvYc7Z715jGh+1hhVAxMaNS3ED/nSPnslyjhq\n"
+ "BUm51LhYNHD4ktISIqPMurx6aC8B68UYgKzLgCYNzkathFXSBpjRAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "uptime forever-and-a-day\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "NHYeiQOu0nZdrhSy31Xz4F0T6OTU23hPQDzoLax1/zq6iTVrz9xi3HGm7HhOMW1j\n"
+ "YgFGK3+Xm4iJL+DwriunsAIuL5axr3z2hlmFDQHYItP//KyPpOqSrfEOhwcuj/PE\n"
+ "VbWsiVYwz9VJLO8SfHoBeHI6PsjQRQFt2REBKZhYdxA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+
+static const char EX_RI_BAD_BANDWIDTH3[] =
+ "router lucy 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAO6HrITQTEjV/v/rInQ2REmCFZa4dZg8zIh6+B51U/I6hDiZaKGwpNey\n"
+ "9OfjoRqT2DwyLEe3ORm9A2RAz2twLBixrpt5IvC0sbGustmW964BHW7k9VvRupwl\n"
+ "ovujHpLIj5dkLxD15jGXHoTp1yHUVk9NkMGN+ahg6y+QhTbIrWbRAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAOEpciJFXauEqs31GMTUTzu6edBj9WtV+sIflhGKvU1KKRfwCgOcuKMx\n"
+ "QiLHHD9AjhMAFGT/qtNbPFkzfYxHKLHw+NLJsxmNtdkYM26FX3ButPiX+69sq9fI\n"
+ "PCHqQy6z/A7hHwtEk6niWgK2PLhAZCg9duAv+mqFVXe2QEBjax/lAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 electric\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Jk0Xk1RMJSjEflNRcp4qznaHKcfe2r0kOc7TdLAnM8zyNDVj6+Bn8HWmyp/oFmf6\n"
+ "xtWKKgkKxriAVIJgqZMchPbr9RuZS+i+cad++FCwpTVkyBP920XWC47jA3ZXSBee\n"
+ "HK6FaoK5LfmUm8XEU9BVhiwISXaUfTdkR8HfzugFbWk=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_NTOR_KEY[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKYDCSr0Jh9d/mJKjnGYAHKNBcxR3EJk6GGLwKUrRpN8z/aHRxdWlZF2\n"
+ "lBml6yQNK/VPftcvOekxrKq3/dISrIFBzFYj6XHNtg31d09UgitVkk0VfRarZiGu\n"
+ "O6Yv55GSJ9a3AZDE4YmIp5eBjVuChyVkeDFYKVn0ed4sj9gg35rjAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALXdUQuq1pYHyYP0qU6Ik+oOmwl0eOsuwiLWf9Vd+dsgEszICX4DRWPx\n"
+ "syDxfxyA/g9FEPvlI7Nglx6cKe2MT0AutSRLbbML4smfuRZNIF35Cnfu5qTGVVzL\n"
+ "GWVSA2Ip7p+9S9xLhLBdc6qmrxEXCPL6anEhCR4f8AeybXAsz2JLAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "ntor-onion-key s7rSohmz9SXn8WWh1EefTHIsWePthsEntQi0WL+ScVfjdklsdfjkf\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Yf9axWyzPudnRvQstNdbtBYo7pGpUEIdECMGcJtFb6v/00pxk4Tt3RiOKa84cOBV\n"
+ "7V9NjOLdqlx88pGz0DNCJKqToIrwjZDeQ8Q1yi9XClLDkC32fQRX4y6vNBZ3LXLe\n"
+ "ayVrdRrb41/DP+E7FP4RNPA5czujTfs8xLBMbGew8AA=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_FINGERPRINT[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM0wDWF2dBLzsmoIDHRugzosCSR9TSvEE0TkvKu6+agfogGtkQJwQ5zO\n"
+ "sGzZbRR+okO7d+QCED2i3rUs1iikoMUT+pwgvOm8Bxg9R64GK7fl9K5WuAiG11Uj\n"
+ "DQAfSx5Fo30+rhOhe16c9CT7xJhj//ZKDbXUW7BrJI8zpuOnvgD5AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKACg1nWM/WjpUiGwlLQsY3Tq1h0RTz/HmOMx/6rTRxS5HLz0KnLg5zV\n"
+ "dvmfhxqQVKBkt1N2+y+qO7x71oFzIsFMfHYWSxOCEo8Nkff1BqAPqxxUHvM0HwJo\n"
+ "d7lswJ/UT1j4+WZNZ4sFIujsIW2/zZqKlxG9xaw0GXJ082Cj9XkPAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "fingerprint 5555\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "mlqyJ/ZGBINKwSNEi7GpNBCMqIVbL0pGAOBYHJF1GbRlU28uRyNyeELIxIK5ZIet\n"
+ "ZzKr7KPvlBxlyolScPhTJfP98TFSubrwYz7NnQv0vLI0bD0OyoBf/9/1GYlzgTso\n"
+ "3mKfnV7THUalpxe9EjQ/x61Yqf26Co0+jYpt8/Ck6tg=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_MISMATCHED_FINGERPRINT[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANUAvwbpGbsAyA+mBwjFkvurtRzdw9btDqNKtPImufIE+q+AFTaCnwPr\n"
+ "kA7vm/O6h6OhgfdYEC2GfYJfwPGM7MDuz+NnuKxUb3qb2DQN2laqow6qWs9La/if\n"
+ "oHKUjC5mNeAgHcbWapx9CygwaFeVW6FBPl6Db6GIRAlywPSX+XMJAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANlSGd+Vm9nLiUk6zgu8dPnSFfw4F0R2GYfmzncIGJWtRFTF9ThW/0av\n"
+ "/9vZAWyVBjjtnpAP5R1BzdJYV2RwimC/6tqoHtkSbCBhdq5Cb/EHG7Xgb8KwNWVJ\n"
+ "NV1EESDwvWnRfSPGTreRw9+2LkdXri17FhDo2GjRxAq/N7YkLK5hAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "fingerprint CC43 DC8E 8C9E 3E6D 59CD 0399 2491 0C8C E1E4 50D2\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Y8MwYBeEfMhoAABK/FgpVRYolZ7jQ2BJL+8Lb6i4yAuk+HeVmPKTX7MqQoekUuin\n"
+ "/HdPKP+g/9HPMS5pCiW4FMwnXAF0ZocPXF0ndmsTuh0/7VWVOUGgvBpPbIW6guvt\n"
+ "sLLQ3Cq9a4Kwmd+koatfLB6xSZjhXmOn7nRy7gOdwJ8=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_HAS_ACCEPT6[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAJfPJNA3zZ77v2nlX2j5dXImcB/NhRtkG8XQgF7z+3H17sqoXgBgZ1dq\n"
+ "IbyJmAy2Lrvk/8VkXNFrT5/ErThn1B98V/PsJOOW1x7jGcix6X4zDYn/MvwC+AxA\n"
+ "zNP0ozNcVZ6BzVYq8w4I1V4O3Cd6VJesxRVX6mUeSeNawOb7fBY7AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKBzfB4mDEJjFTnmtqZxDG8G1yAiccVgAtq9ECEREL/BOQyukixUBeBe\n"
+ "j/FgXzbMJ7DZAuopuJZU2ma6h14G63fZs7eNFceDtmdLpuCOsFuvJ5Mlkf3hDZ1u\n"
+ "1KK5q+tiG7MKxgnGrqjPBUO2uubs2Cpx0HmsqBNUalXd/KAkFJbXAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "accept6 *:80\n"
+ "reject6 *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "Dp9dLgs9s5beMPxfD0m96as9gNBvlmKhH1RQ/kcOKscia4R8Q42CnUtIqLkCdjOu\n"
+ "zErc2Vj9QzjKOvlqUqHxP+J+l+ZJez6F+E1tcmK/Ydz3exL8cg9f4sAOCSXcpBey\n"
+ "llTFDibz6GkQ2j3/Uc4bN/uLzoyZKunpJbSKZP5nt8Q=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_NO_EXIT_POLICY[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAK4fbjTKYqv2fygfjzY53sVTdtbNMjq293/uffKKxFYnOVvPzrHlP6Go\n"
+ "2S19ZcyDxOuH1unbBChPnV0GpxXX6+bgfDkaFh7+jef0RQ3fpJl84hSvdM8J8SCt\n"
+ "Q/F4Oqk3NeKKs+zAHDjhAU1G4LkF9/SZ9WZVXlH4a4pf7xgQtaShAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKahvyDkmh33ob/bLVO1icgz2ntOZN6ZQUfgpMU4Cd6DQtOEwFUGhbVt\n"
+ "gvtMHv2+VbxM31ZfUsyBqJ1rJBLpOqlPvSoYwSac2+twa+w/qjfGqcJYhBjP9TV9\n"
+ "n9y8DzBX85p6vRcCzcuZ4qUJ2nRzdLHwjdgzeLmmCHuPO2dQxQhXAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "ntgCtMC0VrsY42dKts8igGQ2Nu1BpuzUltisIsJz75dDx2LCqTn7p4VpWbTrj1sH\n"
+ "MRNOvEPFxVMs0Lu50ZUGRzeV6GrHmzIRnOIWanb3I/jyrJLM0jTIjCOLwdMRA298\n"
+ "tw8Y9Hnwj4K7K6VvgU8LP4l7MAJNfR6UT46AJ6vkgL0=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_IPV6_EXIT_POLICY[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKHJKLHqjYoW9M+1q0CGHJRT5u2CnZWb8Qr1DpLkkusQ6ru+cDAG12so\n"
+ "IpDQh7IyB2JosVJi9ogekYxJ3O1p5WlFUi0X19DMoer9FJ9J7/3s4enGJ/yMBeuu\n"
+ "jLVRkjMJhsfhj3Cykon+8Rrf520wSmBg1dpJQCXTwtb7DARgYRpZAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAPJH61Ir6XSu9/Q9tXGaINbXO1GWQQUXtwh6TX9lxnaCNDLGnxiY+ZZw\n"
+ "+Vqj3LAQoMrz1PpPsF5e0VIxok10Vc8y4cWC+kIitcecut4vWC5FYTtVVP9wtlyg\n"
+ "YCcVOVhtFQxtLiGqprl84+EVxrR7RQVCMLNDUXIgxAfdnS24eBPDAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "ipv6-policy kfdslfdfj sdjfk sdfjsdf\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "XWorzVT5Owg+QcsBtksiUNtpQQ5+IdvbsN+0O9FbFtGZeaeBAbPJ3Poz+KFCUjZY\n"
+ "DeDAiu1cVgODx2St+99LpwEuIBx78HaD8RYU8tHx8LoA+mGC43ogQQS9lmfxzvP5\n"
+ "eT5WXhkOS5AZ8LZOCOmT+tj/LkSXev2x/NC9+Vc1HPo=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_FAMILY[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM62QoRxSPnm+ZM4fv9p03Qqbz5SzhXYSNjKWqylBruaofTw6oIM8DtX\n"
+ "7QnrEe/ou/WtfB+swV/2rt/r0EzmeWBWuDmuSUrN5TC2AdOi9brSJMgXVW6VW77X\n"
+ "fuIlLd5DVSId2zs3cKLDqp36CUsooA9sS6I5HrvW9QDf3VS3pGBtAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANg1trpnRzkCi4t4Z4qnBKF612H5A3Zrjg7Jo2b3ajUnON/KEuLPTc3t\n"
+ "PPN0W4qqeCMmVQEuxf3DRbTPS20ycy4B/JDWYfxCNwuj5YAx04REf7T0Hlx7Aee/\n"
+ "sHEQBhIBfasA2idhTh3cAm4DMYn+00BqjxF6jmyRA0hyntEABabrAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "family aaaa,bbbb\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "xOgP3liKF/WEvwbbGzUUVRZ5WPrOI7jex8pZU/02UEnHjit7vCf9fsUcvkeo0xjz\n"
+ "n3FQHIO1iAJS7dEaEM4nz6wtPUb2iXSU9QajkGBkJ9/V7NHMFIU3FGfP47PIJJkd\n"
+ "nz5INoS+AsE7PmnDjUMm1H45TCCl8N8y4FO6TtN7p8I=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_BAD_EI_DIGEST[] =
+ "router fred 127.0.0.1 9001 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAJ8Sn8AxBRbeIAHUvaKjqmcYOvXz7YFlpYFiVHp/cn+l+KUkIYTOFQXf\n"
+ "K8AtwjmJ4R2qJIbNlY/6oZGFbizt/B+WPuWsTj+8ACEEDlxx0ibg3EJRB8AZYiWv\n"
+ "0zC/loiUvHm6fXF5ghvDr9BQzEUo9kBk5haoHwROtGawr1+vOEiNAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMzok3ZJtLjXOC8RKltXI8xulwn/ctCvQFHImR0+ccA1uBxaZNYgiIcc\n"
+ "q8XngROfV8xEgDbYPiWiLXJOMSwOd7hfs3YzRWF+LKftYs8PuRyMJcCoBjOPZ4QX\n"
+ "HRfTetEvu2SijZMby+lkqpZg2nuF/ipsXUjrabRZdNiIGhC451vdAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "extra-info-digest not-a-digest\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "c/6zAxO04izQvqdM4bZVGE+ak0nna5pz9XZizFkieZEDWGzWQuVMhXyL5sbsFbsx\n"
+ "6Hn7DvNRYR/2nA0teDeRyIHMoMHi76te5X9OFDgaeUVCbyJ8h/KZYfPnN86IDbsR\n"
+ "dCSmj9kX55keu64ccCAH1CqwcN/UsbplXiJJVG5pTfI=\n"
+ "-----END SIGNATURE-----\n"
+ ;
+static const char EX_RI_ZERO_ORPORT[] =
+ "router fred 127.0.0.1 0 0 9002\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMc4MOhLG3PKPgc+xYVf4eScWzeOf8wq7Cb/JxZm50G0LuvVbhHtHEZX\n"
+ "VOSHI7mLE1ifakJvCFJRLobMU7lU0yhn18/nKl2Cu5NfFHHeF/NieUBSxBGb2wD6\n"
+ "aM1azheXrRqvDVVfbI0DLc/XfQC/YNiohOsQ/c9C6wuffA4+Sg85AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALBWdl9/Vft+NQKQlg5kgvZo+krnhNTRVQojWtUEzom4TFIT+NNKJyMG\n"
+ "reQXcNdzNptTB0aOBGGwqAesqzsZ2Hje699NsDe7hdl7Sb5yhKDqtdQY6yDXJUFt\n"
+ "zqpAUkmYMLe2p3kPiWefNso56KYXrZrlNAiIS/FhQ5cmuMC2jPydAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "published 2014-10-05 12:00:00\n"
+ "bandwidth 1000 1000 1000\n"
+ "reject *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "gFg08P9A6QNQjURlebfdhU3DSV0BeM0j2SFza1jF9JcBOWDRmT8FvYFK1B3js6jK\n"
+ "8LNV8JOUssv14z5CnUY9CO1BD0xSl+vGlSS4VOXD7rxui8IoWgnqnZsitq+Qzs95\n"
+ "wgFKhHI/49NHyWHX5IMQpeicg0T7Qa6qwnUvspH62p8=\n"
+ "-----END SIGNATURE-----\n"
+ ;
diff --git a/src/test/include.am b/src/test/include.am
index 77c92f12f8..8d05b3b700 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -34,6 +34,7 @@ src_test_test_SOURCES = \
src/test/test_logging.c \
src/test/test_microdesc.c \
src/test/test_oom.c \
+ src/test/test_accounting.c \
src/test/test_options.c \
src/test/test_pt.c \
src/test/test_relaycell.c \
@@ -60,7 +61,7 @@ src_test_test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
@TOR_LDFLAGS_libevent@
src_test_test_LDADD = src/or/libtor-testing.a src/common/libor-testing.a \
src/common/libor-crypto-testing.a $(LIBDONNA) \
- src/common/libor-event-testing.a \
+ src/common/libor-event-testing.a src/trunnel/libor-trunnel-testing.a \
@TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ \
@TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@
@@ -74,7 +75,10 @@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \
noinst_HEADERS+= \
src/test/test.h \
- src/test/test_descriptors.inc
+ src/test/test_descriptors.inc \
+ src/test/example_extrainfo.inc \
+ src/test/failing_routerdescs.inc \
+ src/test/ed25519_vectors.inc
if CURVE25519_ENABLED
noinst_PROGRAMS+= src/test/test-ntor-cl
diff --git a/src/test/slow_ed25519.py b/src/test/slow_ed25519.py
new file mode 100644
index 0000000000..f44708b200
--- /dev/null
+++ b/src/test/slow_ed25519.py
@@ -0,0 +1,115 @@
+# This is the ed25519 implementation from
+# http://ed25519.cr.yp.to/python/ed25519.py .
+# It is in the public domain.
+#
+# It isn't constant-time. Don't use it except for testing. Also, see
+# warnings about how very slow it is. Only use this for generating
+# test vectors, I'd suggest.
+#
+# Don't edit this file. Mess with ed25519_ref.py
+
+import hashlib
+
+b = 256
+q = 2**255 - 19
+l = 2**252 + 27742317777372353535851937790883648493
+
+def H(m):
+ return hashlib.sha512(m).digest()
+
+def expmod(b,e,m):
+ if e == 0: return 1
+ t = expmod(b,e/2,m)**2 % m
+ if e & 1: t = (t*b) % m
+ return t
+
+def inv(x):
+ return expmod(x,q-2,q)
+
+d = -121665 * inv(121666)
+I = expmod(2,(q-1)/4,q)
+
+def xrecover(y):
+ xx = (y*y-1) * inv(d*y*y+1)
+ x = expmod(xx,(q+3)/8,q)
+ if (x*x - xx) % q != 0: x = (x*I) % q
+ if x % 2 != 0: x = q-x
+ return x
+
+By = 4 * inv(5)
+Bx = xrecover(By)
+B = [Bx % q,By % q]
+
+def edwards(P,Q):
+ x1 = P[0]
+ y1 = P[1]
+ x2 = Q[0]
+ y2 = Q[1]
+ x3 = (x1*y2+x2*y1) * inv(1+d*x1*x2*y1*y2)
+ y3 = (y1*y2+x1*x2) * inv(1-d*x1*x2*y1*y2)
+ return [x3 % q,y3 % q]
+
+def scalarmult(P,e):
+ if e == 0: return [0,1]
+ Q = scalarmult(P,e/2)
+ Q = edwards(Q,Q)
+ if e & 1: Q = edwards(Q,P)
+ return Q
+
+def encodeint(y):
+ bits = [(y >> i) & 1 for i in range(b)]
+ return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)])
+
+def encodepoint(P):
+ x = P[0]
+ y = P[1]
+ bits = [(y >> i) & 1 for i in range(b - 1)] + [x & 1]
+ return ''.join([chr(sum([bits[i * 8 + j] << j for j in range(8)])) for i in range(b/8)])
+
+def bit(h,i):
+ return (ord(h[i/8]) >> (i%8)) & 1
+
+def publickey(sk):
+ h = H(sk)
+ a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
+ A = scalarmult(B,a)
+ return encodepoint(A)
+
+def Hint(m):
+ h = H(m)
+ return sum(2**i * bit(h,i) for i in range(2*b))
+
+def signature(m,sk,pk):
+ h = H(sk)
+ a = 2**(b-2) + sum(2**i * bit(h,i) for i in range(3,b-2))
+ r = Hint(''.join([h[i] for i in range(b/8,b/4)]) + m)
+ R = scalarmult(B,r)
+ S = (r + Hint(encodepoint(R) + pk + m) * a) % l
+ return encodepoint(R) + encodeint(S)
+
+def isoncurve(P):
+ x = P[0]
+ y = P[1]
+ return (-x*x + y*y - 1 - d*x*x*y*y) % q == 0
+
+def decodeint(s):
+ return sum(2**i * bit(s,i) for i in range(0,b))
+
+def decodepoint(s):
+ y = sum(2**i * bit(s,i) for i in range(0,b-1))
+ x = xrecover(y)
+ if x & 1 != bit(s,b-1): x = q-x
+ P = [x,y]
+ if not isoncurve(P): raise Exception("decoding point that is not on curve")
+ return P
+
+def checkvalid(s,m,pk):
+ if len(s) != b/4: raise Exception("signature length is wrong")
+ if len(pk) != b/8: raise Exception("public-key length is wrong")
+ R = decodepoint(s[0:b/8])
+ A = decodepoint(pk)
+ S = decodeint(s[b/8:b/4])
+ h = Hint(encodepoint(R) + pk + m)
+ if scalarmult(B,S) != edwards(R,scalarmult(A,h)):
+ raise Exception("signature does not pass verification")
+
diff --git a/src/test/test-network.sh b/src/test/test-network.sh
index 7b59864166..d28fbde80f 100755
--- a/src/test/test-network.sh
+++ b/src/test/test-network.sh
@@ -1,5 +1,7 @@
#! /bin/sh
+ECHO_N="/bin/echo -n"
+
until [ -z $1 ]
do
case $1 in
@@ -15,6 +17,10 @@ do
export NETWORK_FLAVOUR="$2"
shift
;;
+ --delay|--sleep|--bootstrap-time|--time)
+ export BOOTSTRAP_TIME="$2"
+ shift
+ ;;
*)
echo "Sorry, I don't know what to do with '$1'."
exit 2
@@ -39,9 +45,14 @@ PATH="$TOR_DIR/src/or:$TOR_DIR/src/tools:$PATH"
# Sleep some, waiting for the network to bootstrap.
# TODO: Add chutney command 'bootstrap-status' and use that instead.
-BOOTSTRAP_TIME=18
-echo -n "$myname: sleeping for $BOOTSTRAP_TIME seconds"
+BOOTSTRAP_TIME=${BOOTSTRAP_TIME:-18}
+$ECHO_N "$myname: sleeping for $BOOTSTRAP_TIME seconds"
n=$BOOTSTRAP_TIME; while [ $n -gt 0 ]; do
- sleep 1; n=$(expr $n - 1); echo -n .
+ sleep 1; n=$(expr $n - 1); $ECHO_N .
done; echo ""
./chutney verify $CHUTNEY_NETWORK
+VERIFY_EXIT_STATUS=$?
+# work around a bug/feature in make -j2 (or more)
+# where make hangs if any child processes are still alive
+./chutney stop $CHUTNEY_NETWORK
+exit $VERIFY_EXIT_STATUS
diff --git a/src/test/test.c b/src/test/test.c
index a14064f237..16ad6f3ae6 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -232,7 +232,7 @@ free_pregenerated_keys(void)
/** Run unit tests for the onion handshake code. */
static void
-test_onion_handshake(void)
+test_onion_handshake(void *arg)
{
/* client-side */
crypto_dh_t *c_dh = NULL;
@@ -245,12 +245,13 @@ test_onion_handshake(void)
/* 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);
- test_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));
+ tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));
for (i = 1; i <= 3; ++i) {
crypto_pk_t *k1, *k2;
@@ -267,16 +268,16 @@ test_onion_handshake(void)
memset(s_buf, 0, TAP_ONIONSKIN_REPLY_LEN);
memset(s_keys, 0, 40);
- test_assert(! onion_skin_TAP_server_handshake(c_buf, k1, k2,
+ tt_assert(! onion_skin_TAP_server_handshake(c_buf, k1, k2,
s_buf, s_keys, 40));
/* client handshake 2 */
memset(c_keys, 0, 40);
- test_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40));
+ tt_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40));
- test_memeq(c_keys, s_keys, 40);
+ tt_mem_op(c_keys,==, s_keys, 40);
memset(s_buf, 0, 40);
- test_memneq(c_keys, s_buf, 40);
+ tt_mem_op(c_keys,!=, s_buf, 40);
}
done:
crypto_dh_free(c_dh);
@@ -323,7 +324,7 @@ test_bad_onion_handshake(void *arg)
/* client handshake 1: do it straight. */
memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
- test_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));
+ 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, ==,
@@ -351,7 +352,7 @@ test_bad_onion_handshake(void *arg)
/* Let the client finish; make sure it can. */
tt_int_op(0, ==,
onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40));
- test_memeq(s_keys, c_keys, 40);
+ tt_mem_op(s_keys,==, c_keys, 40);
/* Client: Case 2: The server sent back a degenerate DH. */
memset(s_buf, 0, sizeof(s_buf));
@@ -408,9 +409,9 @@ test_ntor_handshake(void *arg)
tt_int_op(0, ==, onion_skin_ntor_client_handshake(c_state, s_buf,
c_keys, 400));
- test_memeq(c_keys, s_keys, 400);
+ tt_mem_op(c_keys,==, s_keys, 400);
memset(s_buf, 0, 40);
- test_memneq(c_keys, s_buf, 40);
+ tt_mem_op(c_keys,!=, s_buf, 40);
done:
ntor_handshake_state_free(c_state);
@@ -420,7 +421,7 @@ test_ntor_handshake(void *arg)
/** Run unit tests for the onion queues. */
static void
-test_onion_queues(void)
+test_onion_queues(void *arg)
{
uint8_t buf1[TAP_ONIONSKIN_CHALLENGE_LEN] = {0};
uint8_t buf2[NTOR_ONIONSKIN_LEN] = {0};
@@ -431,6 +432,7 @@ test_onion_queues(void)
create_cell_t *onionskin = NULL, *create2_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 */
create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP,
@@ -438,24 +440,24 @@ test_onion_queues(void)
create_cell_init(create2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR,
NTOR_ONIONSKIN_LEN, buf2);
- test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
- test_eq(0, onion_pending_add(circ1, create1));
+ tt_int_op(0,==, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,==, onion_pending_add(circ1, create1));
create1 = NULL;
- test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(1,==, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
- test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
- test_eq(0, onion_pending_add(circ2, create2));
+ tt_int_op(0,==, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
+ tt_int_op(0,==, onion_pending_add(circ2, create2));
create2 = NULL;
- test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
+ tt_int_op(1,==, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
- test_eq_ptr(circ2, onion_next_task(&onionskin));
- test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
- test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
+ tt_ptr_op(circ2,==, onion_next_task(&onionskin));
+ tt_int_op(1,==, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,==, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
tt_ptr_op(onionskin, ==, create2_ptr);
clear_pending_onions();
- test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
- test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
+ tt_int_op(0,==, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP));
+ tt_int_op(0,==, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR));
done:
circuit_free(TO_CIRCUIT(circ1));
@@ -466,7 +468,7 @@ test_onion_queues(void)
}
static void
-test_circuit_timeout(void)
+test_circuit_timeout(void *arg)
{
/* Plan:
* 1. Generate 1000 samples
@@ -484,6 +486,7 @@ test_circuit_timeout(void)
or_state_t *state=NULL;
int i, runs;
double close_ms;
+ (void)arg;
circuit_build_times_init(&initial);
circuit_build_times_init(&estimate);
circuit_build_times_init(&final);
@@ -518,11 +521,11 @@ test_circuit_timeout(void)
} while (fabs(circuit_build_times_cdf(&initial, timeout0) -
circuit_build_times_cdf(&initial, timeout1)) > 0.02);
- test_assert(estimate.total_build_times <= CBT_NCIRCUITS_TO_OBSERVE);
+ tt_assert(estimate.total_build_times <= CBT_NCIRCUITS_TO_OBSERVE);
circuit_build_times_update_state(&estimate, state);
circuit_build_times_free_timeouts(&final);
- test_assert(circuit_build_times_parse_state(&final, state) == 0);
+ tt_assert(circuit_build_times_parse_state(&final, state) == 0);
circuit_build_times_update_alpha(&final);
timeout2 = circuit_build_times_calculate_timeout(&final,
@@ -532,7 +535,7 @@ test_circuit_timeout(void)
log_notice(LD_CIRC, "Timeout2 is %f, Xm is %d", timeout2, final.Xm);
/* 5% here because some accuracy is lost due to histogram conversion */
- test_assert(fabs(circuit_build_times_cdf(&initial, timeout0) -
+ tt_assert(fabs(circuit_build_times_cdf(&initial, timeout0) -
circuit_build_times_cdf(&initial, timeout2)) < 0.05);
for (runs = 0; runs < 50; runs++) {
@@ -555,8 +558,8 @@ test_circuit_timeout(void)
CBT_DEFAULT_QUANTILE_CUTOFF/100.0));
}
- test_assert(!circuit_build_times_network_check_changed(&estimate));
- test_assert(!circuit_build_times_network_check_changed(&final));
+ tt_assert(!circuit_build_times_network_check_changed(&estimate));
+ tt_assert(!circuit_build_times_network_check_changed(&final));
/* Reset liveness to be non-live */
final.liveness.network_last_live = 0;
@@ -565,27 +568,27 @@ test_circuit_timeout(void)
build_times_idx = estimate.build_times_idx;
total_build_times = estimate.total_build_times;
- test_assert(circuit_build_times_network_check_live(&estimate));
- test_assert(circuit_build_times_network_check_live(&final));
+ tt_assert(circuit_build_times_network_check_live(&estimate));
+ tt_assert(circuit_build_times_network_check_live(&final));
circuit_build_times_count_close(&estimate, 0,
(time_t)(approx_time()-estimate.close_ms/1000.0-1));
circuit_build_times_count_close(&final, 0,
(time_t)(approx_time()-final.close_ms/1000.0-1));
- test_assert(!circuit_build_times_network_check_live(&estimate));
- test_assert(!circuit_build_times_network_check_live(&final));
+ tt_assert(!circuit_build_times_network_check_live(&estimate));
+ tt_assert(!circuit_build_times_network_check_live(&final));
log_info(LD_CIRC, "idx: %d %d, tot: %d %d",
build_times_idx, estimate.build_times_idx,
total_build_times, estimate.total_build_times);
/* Check rollback index. Should match top of loop. */
- test_assert(build_times_idx == estimate.build_times_idx);
+ tt_assert(build_times_idx == estimate.build_times_idx);
// This can fail if estimate.total_build_times == 1000, because
// in that case, rewind actually causes us to lose timeouts
if (total_build_times != CBT_NCIRCUITS_TO_OBSERVE)
- test_assert(total_build_times == estimate.total_build_times);
+ tt_assert(total_build_times == estimate.total_build_times);
/* Now simulate that the network has become live and we need
* a change */
@@ -600,12 +603,12 @@ test_circuit_timeout(void)
}
}
- test_assert(estimate.liveness.after_firsthop_idx == 0);
- test_assert(final.liveness.after_firsthop_idx ==
+ tt_assert(estimate.liveness.after_firsthop_idx == 0);
+ tt_assert(final.liveness.after_firsthop_idx ==
CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT-1);
- test_assert(circuit_build_times_network_check_live(&estimate));
- test_assert(circuit_build_times_network_check_live(&final));
+ tt_assert(circuit_build_times_network_check_live(&estimate));
+ tt_assert(circuit_build_times_network_check_live(&final));
circuit_build_times_count_timeout(&final, 1);
}
@@ -619,7 +622,7 @@ test_circuit_timeout(void)
/** Test encoding and parsing of rendezvous service descriptors. */
static void
-test_rend_fns(void)
+test_rend_fns(void *arg)
{
rend_service_descriptor_t *generated = NULL, *parsed = NULL;
char service_id[DIGEST_LEN];
@@ -642,16 +645,17 @@ test_rend_fns(void)
char address6[] = "foo.bar.abcdefghijklmnop.onion";
char address7[] = ".abcdefghijklmnop.onion";
- test_assert(BAD_HOSTNAME == parse_extended_hostname(address1));
- test_assert(ONION_HOSTNAME == parse_extended_hostname(address2));
- test_streq(address2, "aaaaaaaaaaaaaaaa");
- test_assert(EXIT_HOSTNAME == parse_extended_hostname(address3));
- test_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4));
- test_assert(ONION_HOSTNAME == parse_extended_hostname(address5));
- test_streq(address5, "abcdefghijklmnop");
- test_assert(ONION_HOSTNAME == parse_extended_hostname(address6));
- test_streq(address6, "abcdefghijklmnop");
- test_assert(BAD_HOSTNAME == parse_extended_hostname(address7));
+ (void)arg;
+ tt_assert(BAD_HOSTNAME == parse_extended_hostname(address1));
+ tt_assert(ONION_HOSTNAME == parse_extended_hostname(address2));
+ tt_str_op(address2,==, "aaaaaaaaaaaaaaaa");
+ tt_assert(EXIT_HOSTNAME == parse_extended_hostname(address3));
+ tt_assert(NORMAL_HOSTNAME == parse_extended_hostname(address4));
+ tt_assert(ONION_HOSTNAME == parse_extended_hostname(address5));
+ tt_str_op(address5,==, "abcdefghijklmnop");
+ tt_assert(ONION_HOSTNAME == parse_extended_hostname(address6));
+ tt_str_op(address6,==, "abcdefghijklmnop");
+ tt_assert(BAD_HOSTNAME == parse_extended_hostname(address7));
pk1 = pk_generate(0);
pk2 = pk_generate(1);
@@ -684,40 +688,41 @@ test_rend_fns(void)
intro->intro_key = crypto_pk_dup_key(pk2);
smartlist_add(generated->intro_nodes, intro);
}
- test_assert(rend_encode_v2_descriptors(descs, generated, now, 0,
+ tt_assert(rend_encode_v2_descriptors(descs, generated, now, 0,
REND_NO_AUTH, NULL, NULL) > 0);
- test_assert(rend_compute_v2_desc_id(computed_desc_id, service_id_base32,
+ tt_assert(rend_compute_v2_desc_id(computed_desc_id, service_id_base32,
NULL, now, 0) == 0);
- test_memeq(((rend_encoded_v2_service_descriptor_t *)
- smartlist_get(descs, 0))->desc_id, computed_desc_id, DIGEST_LEN);
- test_assert(rend_parse_v2_service_descriptor(&parsed, parsed_desc_id,
+ tt_mem_op(((rend_encoded_v2_service_descriptor_t *)
+ smartlist_get(descs, 0))->desc_id, ==,
+ computed_desc_id, DIGEST_LEN);
+ tt_assert(rend_parse_v2_service_descriptor(&parsed, parsed_desc_id,
&intro_points_encrypted,
&intro_points_size,
&encoded_size,
&next_desc,
((rend_encoded_v2_service_descriptor_t *)
smartlist_get(descs, 0))->desc_str) == 0);
- test_assert(parsed);
- test_memeq(((rend_encoded_v2_service_descriptor_t *)
- smartlist_get(descs, 0))->desc_id, parsed_desc_id, DIGEST_LEN);
- test_eq(rend_parse_introduction_points(parsed, intro_points_encrypted,
- intro_points_size), 3);
- test_assert(!crypto_pk_cmp_keys(generated->pk, parsed->pk));
- test_eq(parsed->timestamp, now);
- test_eq(parsed->version, 2);
- test_eq(parsed->protocols, 42);
- test_eq(smartlist_len(parsed->intro_nodes), 3);
+ tt_assert(parsed);
+ tt_mem_op(((rend_encoded_v2_service_descriptor_t *)
+ smartlist_get(descs, 0))->desc_id,==, parsed_desc_id, DIGEST_LEN);
+ tt_int_op(rend_parse_introduction_points(parsed, intro_points_encrypted,
+ intro_points_size),==, 3);
+ tt_assert(!crypto_pk_cmp_keys(generated->pk, parsed->pk));
+ tt_int_op(parsed->timestamp,==, now);
+ tt_int_op(parsed->version,==, 2);
+ tt_int_op(parsed->protocols,==, 42);
+ tt_int_op(smartlist_len(parsed->intro_nodes),==, 3);
for (i = 0; i < smartlist_len(parsed->intro_nodes); i++) {
rend_intro_point_t *par_intro = smartlist_get(parsed->intro_nodes, i),
*gen_intro = smartlist_get(generated->intro_nodes, i);
extend_info_t *par_info = par_intro->extend_info;
extend_info_t *gen_info = gen_intro->extend_info;
- test_assert(!crypto_pk_cmp_keys(gen_info->onion_key, par_info->onion_key));
- test_memeq(gen_info->identity_digest, par_info->identity_digest,
+ tt_assert(!crypto_pk_cmp_keys(gen_info->onion_key, par_info->onion_key));
+ tt_mem_op(gen_info->identity_digest,==, par_info->identity_digest,
DIGEST_LEN);
- test_streq(gen_info->nickname, par_info->nickname);
- test_assert(tor_addr_eq(&gen_info->addr, &par_info->addr));
- test_eq(gen_info->port, par_info->port);
+ tt_str_op(gen_info->nickname,==, par_info->nickname);
+ tt_assert(tor_addr_eq(&gen_info->addr, &par_info->addr));
+ tt_int_op(gen_info->port,==, par_info->port);
}
rend_service_descriptor_free(parsed);
@@ -761,17 +766,17 @@ test_rend_fns(void)
} while (0)
#define CHECK_COUNTRY(country, val) do { \
/* test ipv4 country lookup */ \
- test_streq(country, \
+ tt_str_op(country, ==, \
geoip_get_country_name(geoip_get_country_by_ipv4(val))); \
/* test ipv6 country lookup */ \
SET_TEST_IPV6(val); \
- test_streq(country, \
+ tt_str_op(country, ==, \
geoip_get_country_name(geoip_get_country_by_ipv6(&in6))); \
} while (0)
/** Run unit tests for GeoIP code. */
static void
-test_geoip(void)
+test_geoip(void *arg)
{
int i, j;
time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
@@ -825,23 +830,24 @@ test_geoip(void)
/* Populate the DB a bit. Add these in order, since we can't do the final
* 'sort' step. These aren't very good IP addresses, but they're perfectly
* fine uint32_t values. */
- test_eq(0, geoip_parse_entry("10,50,AB", AF_INET));
- test_eq(0, geoip_parse_entry("52,90,XY", AF_INET));
- test_eq(0, geoip_parse_entry("95,100,AB", AF_INET));
- test_eq(0, geoip_parse_entry("\"105\",\"140\",\"ZZ\"", AF_INET));
- test_eq(0, geoip_parse_entry("\"150\",\"190\",\"XY\"", AF_INET));
- test_eq(0, geoip_parse_entry("\"200\",\"250\",\"AB\"", AF_INET));
+ (void)arg;
+ tt_int_op(0,==, geoip_parse_entry("10,50,AB", AF_INET));
+ tt_int_op(0,==, geoip_parse_entry("52,90,XY", AF_INET));
+ tt_int_op(0,==, geoip_parse_entry("95,100,AB", AF_INET));
+ tt_int_op(0,==, geoip_parse_entry("\"105\",\"140\",\"ZZ\"", AF_INET));
+ tt_int_op(0,==, geoip_parse_entry("\"150\",\"190\",\"XY\"", AF_INET));
+ tt_int_op(0,==, geoip_parse_entry("\"200\",\"250\",\"AB\"", AF_INET));
/* Populate the IPv6 DB equivalently with fake IPs in the same range */
- test_eq(0, geoip_parse_entry("::a,::32,AB", AF_INET6));
- test_eq(0, geoip_parse_entry("::34,::5a,XY", AF_INET6));
- test_eq(0, geoip_parse_entry("::5f,::64,AB", AF_INET6));
- test_eq(0, geoip_parse_entry("::69,::8c,ZZ", AF_INET6));
- test_eq(0, geoip_parse_entry("::96,::be,XY", AF_INET6));
- test_eq(0, geoip_parse_entry("::c8,::fa,AB", AF_INET6));
+ tt_int_op(0,==, geoip_parse_entry("::a,::32,AB", AF_INET6));
+ tt_int_op(0,==, geoip_parse_entry("::34,::5a,XY", AF_INET6));
+ tt_int_op(0,==, geoip_parse_entry("::5f,::64,AB", AF_INET6));
+ tt_int_op(0,==, geoip_parse_entry("::69,::8c,ZZ", AF_INET6));
+ tt_int_op(0,==, geoip_parse_entry("::96,::be,XY", AF_INET6));
+ tt_int_op(0,==, geoip_parse_entry("::c8,::fa,AB", AF_INET6));
/* We should have 4 countries: ??, ab, xy, zz. */
- test_eq(4, geoip_get_n_countries());
+ tt_int_op(4,==, geoip_get_n_countries());
memset(&in6, 0, sizeof(in6));
CHECK_COUNTRY("??", 3);
@@ -852,9 +858,9 @@ test_geoip(void)
CHECK_COUNTRY("xy", 190);
CHECK_COUNTRY("??", 2000);
- test_eq(0, geoip_get_country_by_ipv4(3));
+ tt_int_op(0,==, geoip_get_country_by_ipv4(3));
SET_TEST_IPV6(3);
- test_eq(0, geoip_get_country_by_ipv6(&in6));
+ tt_int_op(0,==, geoip_get_country_by_ipv6(&in6));
get_options_mutable()->BridgeRelay = 1;
get_options_mutable()->BridgeRecordUsageByCountry = 1;
@@ -877,41 +883,41 @@ test_geoip(void)
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
}
geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
- test_assert(s);
- test_assert(v);
- test_streq("zz=24,ab=16,xy=8", s);
- test_streq("v4=16,v6=16", v);
+ tt_assert(s);
+ tt_assert(v);
+ tt_str_op("zz=24,ab=16,xy=8",==, s);
+ tt_str_op("v4=16,v6=16",==, v);
tor_free(s);
tor_free(v);
/* Now clear out all the AB observations. */
geoip_remove_old_clients(now-6000);
geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
- test_assert(s);
- test_assert(v);
- test_streq("zz=24,xy=8", s);
- test_streq("v4=16,v6=16", v);
+ tt_assert(s);
+ tt_assert(v);
+ tt_str_op("zz=24,xy=8",==, s);
+ tt_str_op("v4=16,v6=16",==, v);
tor_free(s);
tor_free(v);
/* Start testing bridge statistics by making sure that we don't output
* bridge stats without initializing them. */
s = geoip_format_bridge_stats(now + 86400);
- test_assert(!s);
+ tt_assert(!s);
/* Initialize stats and generate the bridge-stats history string out of
* the connecting clients added above. */
geoip_bridge_stats_init(now);
s = geoip_format_bridge_stats(now + 86400);
- test_assert(s);
- test_streq(bridge_stats_1, s);
+ tt_assert(s);
+ tt_str_op(bridge_stats_1,==, s);
tor_free(s);
/* Stop collecting bridge stats and make sure we don't write a history
* string anymore. */
geoip_bridge_stats_term();
s = geoip_format_bridge_stats(now + 86400);
- test_assert(!s);
+ tt_assert(!s);
/* Stop being a bridge and start being a directory mirror that gathers
* directory request statistics. */
@@ -925,7 +931,7 @@ test_geoip(void)
SET_TEST_ADDRESS(100);
geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
s = geoip_format_dirreq_stats(now + 86400);
- test_assert(!s);
+ tt_assert(!s);
/* Initialize stats, note one connecting client, and generate the
* dirreq-stats history string. */
@@ -933,7 +939,7 @@ test_geoip(void)
SET_TEST_ADDRESS(100);
geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
s = geoip_format_dirreq_stats(now + 86400);
- test_streq(dirreq_stats_1, s);
+ tt_str_op(dirreq_stats_1,==, s);
tor_free(s);
/* Stop collecting stats, add another connecting client, and ensure we
@@ -942,7 +948,7 @@ test_geoip(void)
SET_TEST_ADDRESS(101);
geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
s = geoip_format_dirreq_stats(now + 86400);
- test_assert(!s);
+ tt_assert(!s);
/* Re-start stats, add a connecting client, reset stats, and make sure
* that we get an all empty history string. */
@@ -951,20 +957,20 @@ test_geoip(void)
geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
geoip_reset_dirreq_stats(now);
s = geoip_format_dirreq_stats(now + 86400);
- test_streq(dirreq_stats_2, s);
+ tt_str_op(dirreq_stats_2,==, s);
tor_free(s);
/* Note a successful network status response and make sure that it
* appears in the history string. */
geoip_note_ns_response(GEOIP_SUCCESS);
s = geoip_format_dirreq_stats(now + 86400);
- test_streq(dirreq_stats_3, s);
+ tt_str_op(dirreq_stats_3,==, s);
tor_free(s);
/* Start a tunneled directory request. */
geoip_start_dirreq((uint64_t) 1, 1024, DIRREQ_TUNNELED);
s = geoip_format_dirreq_stats(now + 86400);
- test_streq(dirreq_stats_4, s);
+ tt_str_op(dirreq_stats_4,==, s);
tor_free(s);
/* Stop collecting directory request statistics and start gathering
@@ -978,7 +984,7 @@ test_geoip(void)
SET_TEST_ADDRESS(100);
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
s = geoip_format_entry_stats(now + 86400);
- test_assert(!s);
+ tt_assert(!s);
/* Initialize stats, note one connecting client, and generate the
* entry-stats history string. */
@@ -986,7 +992,7 @@ test_geoip(void)
SET_TEST_ADDRESS(100);
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
s = geoip_format_entry_stats(now + 86400);
- test_streq(entry_stats_1, s);
+ tt_str_op(entry_stats_1,==, s);
tor_free(s);
/* Stop collecting stats, add another connecting client, and ensure we
@@ -995,7 +1001,7 @@ test_geoip(void)
SET_TEST_ADDRESS(101);
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
s = geoip_format_entry_stats(now + 86400);
- test_assert(!s);
+ tt_assert(!s);
/* Re-start stats, add a connecting client, reset stats, and make sure
* that we get an all empty history string. */
@@ -1004,7 +1010,7 @@ test_geoip(void)
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
geoip_reset_entry_stats(now);
s = geoip_format_entry_stats(now + 86400);
- test_streq(entry_stats_2, s);
+ tt_str_op(entry_stats_2,==, s);
tor_free(s);
/* Stop collecting entry statistics. */
@@ -1017,7 +1023,7 @@ test_geoip(void)
}
static void
-test_geoip_with_pt(void)
+test_geoip_with_pt(void *arg)
{
time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
char *s = NULL;
@@ -1025,6 +1031,7 @@ test_geoip_with_pt(void)
tor_addr_t addr;
struct in6_addr in6;
+ (void)arg;
get_options_mutable()->BridgeRelay = 1;
get_options_mutable()->BridgeRecordUsageByCountry = 1;
@@ -1076,7 +1083,7 @@ test_geoip_with_pt(void)
/* Test the transport history string. */
s = geoip_get_transport_history();
tor_assert(s);
- test_streq(s, "<OR>=8,alpha=16,beta=8,charlie=16,ddr=136,"
+ tt_str_op(s,==, "<OR>=8,alpha=16,beta=8,charlie=16,ddr=136,"
"entropy=8,fire=8,google=8");
/* Stop collecting entry statistics. */
@@ -1093,7 +1100,7 @@ test_geoip_with_pt(void)
/** Run unit tests for stats code. */
static void
-test_stats(void)
+test_stats(void *arg)
{
time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
char *s = NULL;
@@ -1101,10 +1108,11 @@ test_stats(void)
/* Start with testing exit port statistics; we shouldn't collect exit
* stats without initializing them. */
+ (void)arg;
rep_hist_note_exit_stream_opened(80);
rep_hist_note_exit_bytes(80, 100, 10000);
s = rep_hist_format_exit_stats(now + 86400);
- test_assert(!s);
+ tt_assert(!s);
/* Initialize stats, note some streams and bytes, and generate history
* string. */
@@ -1115,10 +1123,10 @@ test_stats(void)
rep_hist_note_exit_bytes(443, 100, 10000);
rep_hist_note_exit_bytes(443, 100, 10000);
s = rep_hist_format_exit_stats(now + 86400);
- test_streq("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
"exit-kibibytes-written 80=1,443=1,other=0\n"
"exit-kibibytes-read 80=10,443=20,other=0\n"
- "exit-streams-opened 80=4,443=4,other=0\n", s);
+ "exit-streams-opened 80=4,443=4,other=0\n",==, s);
tor_free(s);
/* Add a few bytes on 10 more ports and ensure that only the top 10
@@ -1128,13 +1136,13 @@ test_stats(void)
rep_hist_note_exit_stream_opened(i);
}
s = rep_hist_format_exit_stats(now + 86400);
- test_streq("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
"exit-kibibytes-written 52=1,53=1,54=1,55=1,56=1,57=1,58=1,"
"59=1,80=1,443=1,other=1\n"
"exit-kibibytes-read 52=1,53=1,54=1,55=1,56=1,57=1,58=1,"
"59=1,80=10,443=20,other=1\n"
"exit-streams-opened 52=4,53=4,54=4,55=4,56=4,57=4,58=4,"
- "59=4,80=4,443=4,other=4\n", s);
+ "59=4,80=4,443=4,other=4\n",==, s);
tor_free(s);
/* Stop collecting stats, add some bytes, and ensure we don't generate
@@ -1142,7 +1150,7 @@ test_stats(void)
rep_hist_exit_stats_term();
rep_hist_note_exit_bytes(80, 100, 10000);
s = rep_hist_format_exit_stats(now + 86400);
- test_assert(!s);
+ tt_assert(!s);
/* Re-start stats, add some bytes, reset stats, and see what history we
* get when observing no streams or bytes at all. */
@@ -1151,17 +1159,17 @@ test_stats(void)
rep_hist_note_exit_bytes(80, 100, 10000);
rep_hist_reset_exit_stats(now);
s = rep_hist_format_exit_stats(now + 86400);
- test_streq("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n"
"exit-kibibytes-written other=0\n"
"exit-kibibytes-read other=0\n"
- "exit-streams-opened other=0\n", s);
+ "exit-streams-opened other=0\n",==, s);
tor_free(s);
/* Continue with testing connection statistics; we shouldn't collect
* conn stats without initializing them. */
rep_hist_note_or_conn_bytes(1, 20, 400, now);
s = rep_hist_format_conn_stats(now + 86400);
- test_assert(!s);
+ tt_assert(!s);
/* Initialize stats, note bytes, and generate history string. */
rep_hist_conn_stats_init(now);
@@ -1170,7 +1178,7 @@ test_stats(void)
rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
s = rep_hist_format_conn_stats(now + 86400);
- test_streq("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n", s);
+ tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n",==, s);
tor_free(s);
/* Stop collecting stats, add some bytes, and ensure we don't generate
@@ -1178,7 +1186,7 @@ test_stats(void)
rep_hist_conn_stats_term();
rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
s = rep_hist_format_conn_stats(now + 86400);
- test_assert(!s);
+ tt_assert(!s);
/* Re-start stats, add some bytes, reset stats, and see what history we
* get when observing no bytes at all. */
@@ -1189,26 +1197,26 @@ test_stats(void)
rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
rep_hist_reset_conn_stats(now);
s = rep_hist_format_conn_stats(now + 86400);
- test_streq("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n", s);
+ tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",==, s);
tor_free(s);
/* Continue with testing buffer statistics; we shouldn't collect buffer
* stats without initializing them. */
rep_hist_add_buffer_stats(2.0, 2.0, 20);
s = rep_hist_format_buffer_stats(now + 86400);
- test_assert(!s);
+ tt_assert(!s);
/* Initialize stats, add statistics for a single circuit, and generate
* the history string. */
rep_hist_buffer_stats_init(now);
rep_hist_add_buffer_stats(2.0, 2.0, 20);
s = rep_hist_format_buffer_stats(now + 86400);
- test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
"cell-processed-cells 20,0,0,0,0,0,0,0,0,0\n"
"cell-queued-cells 2.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
"0.00,0.00\n"
"cell-time-in-queue 2,0,0,0,0,0,0,0,0,0\n"
- "cell-circuits-per-decile 1\n", s);
+ "cell-circuits-per-decile 1\n",==, s);
tor_free(s);
/* Add nineteen more circuit statistics to the one that's already in the
@@ -1218,12 +1226,12 @@ test_stats(void)
for (i = 20; i < 30; i++)
rep_hist_add_buffer_stats(3.5, 3.5, i);
s = rep_hist_format_buffer_stats(now + 86400);
- test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
"cell-processed-cells 29,28,27,26,25,24,23,22,21,20\n"
"cell-queued-cells 2.75,2.75,2.75,2.75,2.75,2.75,2.75,2.75,"
"2.75,2.75\n"
"cell-time-in-queue 3,3,3,3,3,3,3,3,3,3\n"
- "cell-circuits-per-decile 2\n", s);
+ "cell-circuits-per-decile 2\n",==, s);
tor_free(s);
/* Stop collecting stats, add statistics for one circuit, and ensure we
@@ -1231,7 +1239,7 @@ test_stats(void)
rep_hist_buffer_stats_term();
rep_hist_add_buffer_stats(2.0, 2.0, 20);
s = rep_hist_format_buffer_stats(now + 86400);
- test_assert(!s);
+ tt_assert(!s);
/* Re-start stats, add statistics for one circuit, reset stats, and make
* sure that the history has all zeros. */
@@ -1239,46 +1247,21 @@ test_stats(void)
rep_hist_add_buffer_stats(2.0, 2.0, 20);
rep_hist_reset_buffer_stats(now);
s = rep_hist_format_buffer_stats(now + 86400);
- test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
"cell-processed-cells 0,0,0,0,0,0,0,0,0,0\n"
"cell-queued-cells 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
"0.00,0.00\n"
"cell-time-in-queue 0,0,0,0,0,0,0,0,0,0\n"
- "cell-circuits-per-decile 0\n", s);
+ "cell-circuits-per-decile 0\n",==, s);
done:
tor_free(s);
}
-static void *
-legacy_test_setup(const struct testcase_t *testcase)
-{
- return testcase->setup_data;
-}
-
-void
-legacy_test_helper(void *data)
-{
- void (*fn)(void) = data;
- fn();
-}
-
-static int
-legacy_test_cleanup(const struct testcase_t *testcase, void *ptr)
-{
- (void)ptr;
- (void)testcase;
- return 1;
-}
-
-const struct testcase_setup_t legacy_setup = {
- legacy_test_setup, legacy_test_cleanup
-};
-
#define ENT(name) \
- { #name, legacy_test_helper, 0, &legacy_setup, test_ ## name }
+ { #name, test_ ## name , 0, NULL, NULL }
#define FORK(name) \
- { #name, legacy_test_helper, TT_FORK, &legacy_setup, test_ ## name }
+ { #name, test_ ## name , TT_FORK, NULL, NULL }
static struct testcase_t test_array[] = {
ENT(onion_handshake),
@@ -1322,6 +1305,7 @@ extern struct testcase_t hs_tests[];
extern struct testcase_t nodelist_tests[];
extern struct testcase_t routerkeys_tests[];
extern struct testcase_t oom_tests[];
+extern struct testcase_t accounting_tests[];
extern struct testcase_t policy_tests[];
extern struct testcase_t status_tests[];
extern struct testcase_t routerset_tests[];
@@ -1354,6 +1338,7 @@ static struct testgroup_t testgroups[] = {
{ "nodelist/", nodelist_tests },
{ "routerkeys/", routerkeys_tests },
{ "oom/", oom_tests },
+ { "accounting/", accounting_tests },
{ "policy/" , policy_tests },
{ "status/" , status_tests },
{ "routerset/" , routerset_tests },
diff --git a/src/test/test.h b/src/test/test.h
index b9e4d5bdb4..8eb2dfc016 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -22,25 +22,6 @@
#define PRETTY_FUNCTION ""
#endif
-#define test_fail_msg(msg) TT_DIE((msg))
-
-#define test_fail() test_fail_msg("Assertion failed.")
-
-#define test_assert(expr) tt_assert(expr)
-
-#define test_eq(expr1, expr2) tt_int_op((expr1), ==, (expr2))
-#define test_eq_ptr(expr1, expr2) tt_ptr_op((expr1), ==, (expr2))
-#define test_neq(expr1, expr2) tt_int_op((expr1), !=, (expr2))
-#define test_neq_ptr(expr1, expr2) tt_ptr_op((expr1), !=, (expr2))
-#define test_streq(expr1, expr2) tt_str_op((expr1), ==, (expr2))
-#define test_strneq(expr1, expr2) tt_str_op((expr1), !=, (expr2))
-
-#define test_mem_op(expr1, op, expr2, len) \
- tt_mem_op((expr1), op, (expr2), (len))
-
-#define test_memeq(expr1, expr2, len) test_mem_op((expr1), ==, (expr2), len)
-#define test_memneq(expr1, expr2, len) test_mem_op((expr1), !=, (expr2), len)
-
/* As test_mem_op, but decodes 'hex' before comparing. There must be a
* local char* variable called mem_op_hex_tmp for this to work. */
#define test_mem_op_hex(expr1, op, hex) \
@@ -50,7 +31,7 @@
mem_op_hex_tmp = tor_malloc(length/2); \
tor_assert((length&1)==0); \
base16_decode(mem_op_hex_tmp, length/2, hex, length); \
- test_mem_op(expr1, op, mem_op_hex_tmp, length/2); \
+ tt_mem_op(expr1, op, mem_op_hex_tmp, length/2); \
STMT_END
#define test_memeq_hex(expr1, hex) test_mem_op_hex(expr1, ==, hex)
@@ -85,9 +66,6 @@
const char *get_fname(const char *name);
crypto_pk_t *pk_generate(int idx);
-void legacy_test_helper(void *data);
-extern const struct testcase_setup_t legacy_setup;
-
#define US2_CONCAT_2__(a, b) a ## __ ## b
#define US_CONCAT_2__(a, b) a ## _ ## b
#define US_CONCAT_3__(a, b, c) a ## _ ## b ## _ ## c
diff --git a/src/test/test_accounting.c b/src/test/test_accounting.c
new file mode 100644
index 0000000000..25908e942c
--- /dev/null
+++ b/src/test/test_accounting.c
@@ -0,0 +1,76 @@
+#include "or.h"
+#include "test.h"
+#define HIBERNATE_PRIVATE
+#include "hibernate.h"
+#include "config.h"
+#define STATEFILE_PRIVATE
+#include "statefile.h"
+
+#define NS_MODULE accounting
+
+#define NS_SUBMODULE limits
+
+/*
+ * Test to make sure accounting triggers hibernation
+ * correctly with both sum or max rules set
+ */
+
+static or_state_t *or_state;
+NS_DECL(or_state_t *, get_or_state, (void));
+static or_state_t *
+NS(get_or_state)(void)
+{
+ return or_state;
+}
+
+static void
+test_accounting_limits(void *arg)
+{
+ or_options_t *options = get_options_mutable();
+ time_t fake_time = time(NULL);
+ (void) arg;
+
+ NS_MOCK(get_or_state);
+ or_state = or_state_new();
+
+ options->AccountingMax = 100;
+ options->AccountingRule = ACCT_MAX;
+
+ tor_assert(accounting_is_enabled(options));
+ configure_accounting(fake_time);
+
+ accounting_add_bytes(10, 0, 1);
+ fake_time += 1;
+ consider_hibernation(fake_time);
+ tor_assert(we_are_hibernating() == 0);
+
+ accounting_add_bytes(90, 0, 1);
+ fake_time += 1;
+ consider_hibernation(fake_time);
+ tor_assert(we_are_hibernating() == 1);
+
+ options->AccountingMax = 200;
+ options->AccountingRule = ACCT_SUM;
+
+ accounting_add_bytes(0, 10, 1);
+ fake_time += 1;
+ consider_hibernation(fake_time);
+ tor_assert(we_are_hibernating() == 0);
+
+ accounting_add_bytes(0, 90, 1);
+ fake_time += 1;
+ consider_hibernation(fake_time);
+ tor_assert(we_are_hibernating() == 1);
+ goto done;
+ done:
+ NS_UNMOCK(get_or_state);
+ or_state_free(or_state);
+}
+
+#undef NS_SUBMODULE
+
+struct testcase_t accounting_tests[] = {
+ { "bwlimits", test_accounting_limits, TT_FORK, NULL, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index 50011e606b..043c2a0d4a 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -10,49 +10,50 @@
#include "addressmap.h"
static void
-test_addr_basic(void)
+test_addr_basic(void *arg)
{
uint32_t u32;
uint16_t u16;
char *cp;
/* Test addr_port_lookup */
+ (void)arg;
cp = NULL; u32 = 3; u16 = 3;
- test_assert(!addr_port_lookup(LOG_WARN, "1.2.3.4", &cp, &u32, &u16));
- test_streq(cp, "1.2.3.4");
- test_eq(u32, 0x01020304u);
- test_eq(u16, 0);
+ tt_assert(!addr_port_lookup(LOG_WARN, "1.2.3.4", &cp, &u32, &u16));
+ tt_str_op(cp,==, "1.2.3.4");
+ tt_int_op(u32,==, 0x01020304u);
+ tt_int_op(u16,==, 0);
tor_free(cp);
- test_assert(!addr_port_lookup(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16));
- test_streq(cp, "4.3.2.1");
- test_eq(u32, 0x04030201u);
- test_eq(u16, 99);
+ tt_assert(!addr_port_lookup(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16));
+ tt_str_op(cp,==, "4.3.2.1");
+ tt_int_op(u32,==, 0x04030201u);
+ tt_int_op(u16,==, 99);
tor_free(cp);
- test_assert(!addr_port_lookup(LOG_WARN, "nonexistent.address:4040",
+ tt_assert(!addr_port_lookup(LOG_WARN, "nonexistent.address:4040",
&cp, NULL, &u16));
- test_streq(cp, "nonexistent.address");
- test_eq(u16, 4040);
+ tt_str_op(cp,==, "nonexistent.address");
+ tt_int_op(u16,==, 4040);
tor_free(cp);
- test_assert(!addr_port_lookup(LOG_WARN, "localhost:9999", &cp, &u32, &u16));
- test_streq(cp, "localhost");
- test_eq(u32, 0x7f000001u);
- test_eq(u16, 9999);
+ tt_assert(!addr_port_lookup(LOG_WARN, "localhost:9999", &cp, &u32, &u16));
+ tt_str_op(cp,==, "localhost");
+ tt_int_op(u32,==, 0x7f000001u);
+ tt_int_op(u16,==, 9999);
tor_free(cp);
u32 = 3;
- test_assert(!addr_port_lookup(LOG_WARN, "localhost", NULL, &u32, &u16));
- test_eq_ptr(cp, NULL);
- test_eq(u32, 0x7f000001u);
- test_eq(u16, 0);
+ tt_assert(!addr_port_lookup(LOG_WARN, "localhost", NULL, &u32, &u16));
+ tt_ptr_op(cp,==, NULL);
+ tt_int_op(u32,==, 0x7f000001u);
+ tt_int_op(u16,==, 0);
tor_free(cp);
- test_assert(addr_port_lookup(LOG_WARN, "localhost:3", &cp, &u32, NULL));
+ tt_assert(addr_port_lookup(LOG_WARN, "localhost:3", &cp, &u32, NULL));
tor_free(cp);
- test_eq(0, addr_mask_get_bits(0x0u));
- test_eq(32, addr_mask_get_bits(0xFFFFFFFFu));
- test_eq(16, addr_mask_get_bits(0xFFFF0000u));
- test_eq(31, addr_mask_get_bits(0xFFFFFFFEu));
- test_eq(1, addr_mask_get_bits(0x80000000u));
+ tt_int_op(0,==, addr_mask_get_bits(0x0u));
+ tt_int_op(32,==, addr_mask_get_bits(0xFFFFFFFFu));
+ tt_int_op(16,==, addr_mask_get_bits(0xFFFF0000u));
+ tt_int_op(31,==, addr_mask_get_bits(0xFFFFFFFEu));
+ tt_int_op(1,==, addr_mask_get_bits(0x80000000u));
/* Test inet_ntop */
{
@@ -61,15 +62,15 @@ test_addr_basic(void)
struct in_addr in;
/* good round trip */
- test_eq(tor_inet_pton(AF_INET, ip, &in), 1);
- test_eq_ptr(tor_inet_ntop(AF_INET, &in, tmpbuf, sizeof(tmpbuf)), &tmpbuf);
- test_streq(tmpbuf, ip);
+ tt_int_op(tor_inet_pton(AF_INET, ip, &in),==, 1);
+ tt_ptr_op(tor_inet_ntop(AF_INET, &in, tmpbuf, sizeof(tmpbuf)),==, &tmpbuf);
+ tt_str_op(tmpbuf,==, ip);
/* just enough buffer length */
- test_streq(tor_inet_ntop(AF_INET, &in, tmpbuf, strlen(ip) + 1), ip);
+ tt_str_op(tor_inet_ntop(AF_INET, &in, tmpbuf, strlen(ip) + 1),==, ip);
/* too short buffer */
- test_eq_ptr(tor_inet_ntop(AF_INET, &in, tmpbuf, strlen(ip)), NULL);
+ tt_ptr_op(tor_inet_ntop(AF_INET, &in, tmpbuf, strlen(ip)),==, NULL);
}
done:
@@ -96,67 +97,68 @@ test_addr_basic(void)
/** Helper: Assert that two strings both decode as IPv6 addresses with
* tor_inet_pton(), and both decode to the same address. */
-#define test_pton6_same(a,b) STMT_BEGIN \
- test_eq(tor_inet_pton(AF_INET6, a, &a1), 1); \
- test_eq(tor_inet_pton(AF_INET6, b, &a2), 1); \
- test_op_ip6_(&a1,==,&a2,#a,#b); \
+#define test_pton6_same(a,b) STMT_BEGIN \
+ tt_int_op(tor_inet_pton(AF_INET6, a, &a1), ==, 1); \
+ tt_int_op(tor_inet_pton(AF_INET6, b, &a2), ==, 1); \
+ test_op_ip6_(&a1,==,&a2,#a,#b); \
STMT_END
/** Helper: Assert that <b>a</b> is recognized as a bad IPv6 address by
* tor_inet_pton(). */
#define test_pton6_bad(a) \
- test_eq(0, tor_inet_pton(AF_INET6, a, &a1))
+ tt_int_op(0, ==, tor_inet_pton(AF_INET6, a, &a1))
/** Helper: assert that <b>a</b>, when parsed by tor_inet_pton() and displayed
* with tor_inet_ntop(), yields <b>b</b>. Also assert that <b>b</b> parses to
* the same value as <b>a</b>. */
-#define test_ntop6_reduces(a,b) STMT_BEGIN \
- test_eq(tor_inet_pton(AF_INET6, a, &a1), 1); \
- test_streq(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), b); \
- test_eq(tor_inet_pton(AF_INET6, b, &a2), 1); \
- test_op_ip6_(&a1, ==, &a2, a, b); \
+#define test_ntop6_reduces(a,b) STMT_BEGIN \
+ tt_int_op(tor_inet_pton(AF_INET6, a, &a1), ==, 1); \
+ tt_str_op(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), ==, b); \
+ tt_int_op(tor_inet_pton(AF_INET6, b, &a2), ==, 1); \
+ test_op_ip6_(&a1, ==, &a2, a, b); \
STMT_END
/** Helper: assert that <b>a</b> parses by tor_inet_pton() into a address that
* passes tor_addr_is_internal() with <b>for_listening</b>. */
#define test_internal_ip(a,for_listening) STMT_BEGIN \
- test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \
+ tt_int_op(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), ==, 1); \
t1.family = AF_INET6; \
if (!tor_addr_is_internal(&t1, for_listening)) \
- test_fail_msg( a "was not internal."); \
+ TT_DIE(("%s was not internal", a)); \
STMT_END
/** Helper: assert that <b>a</b> parses by tor_inet_pton() into a address that
* does not pass tor_addr_is_internal() with <b>for_listening</b>. */
#define test_external_ip(a,for_listening) STMT_BEGIN \
- test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \
+ tt_int_op(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), ==, 1); \
t1.family = AF_INET6; \
if (tor_addr_is_internal(&t1, for_listening)) \
- test_fail_msg(a "was not external."); \
+ TT_DIE(("%s was not internal", a)); \
STMT_END
/** Helper: Assert that <b>a</b> and <b>b</b>, when parsed by
* tor_inet_pton(), give addresses that compare in the order defined by
* <b>op</b> with tor_addr_compare(). */
#define test_addr_compare(a, op, b) STMT_BEGIN \
- test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \
- test_eq(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), 1); \
+ tt_int_op(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), ==, 1); \
+ tt_int_op(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), ==, 1); \
t1.family = t2.family = AF_INET6; \
r = tor_addr_compare(&t1,&t2,CMP_SEMANTIC); \
if (!(r op 0)) \
- test_fail_msg("failed: tor_addr_compare("a","b") "#op" 0"); \
+ TT_DIE(("Failed: tor_addr_compare(%s,%s) %s 0", a, b, #op));\
STMT_END
/** Helper: Assert that <b>a</b> and <b>b</b>, when parsed by
* tor_inet_pton(), give addresses that compare in the order defined by
* <b>op</b> with tor_addr_compare_masked() with <b>m</b> masked. */
#define test_addr_compare_masked(a, op, b, m) STMT_BEGIN \
- test_eq(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), 1); \
- test_eq(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), 1); \
+ tt_int_op(tor_inet_pton(AF_INET6, a, &t1.addr.in6_addr), ==, 1); \
+ tt_int_op(tor_inet_pton(AF_INET6, b, &t2.addr.in6_addr), ==, 1); \
t1.family = t2.family = AF_INET6; \
r = tor_addr_compare_masked(&t1,&t2,m,CMP_SEMANTIC); \
if (!(r op 0)) \
- test_fail_msg("failed: tor_addr_compare_masked("a","b","#m") "#op" 0"); \
+ TT_DIE(("Failed: tor_addr_compare_masked(%s,%s,%d) %s 0", \
+ a, b, m, #op)); \
STMT_END
/** Helper: assert that <b>xx</b> is parseable as a masked IPv6 address with
@@ -165,21 +167,21 @@ test_addr_basic(void)
* as <b>pt1..pt2</b>. */
#define test_addr_mask_ports_parse(xx, f, ip1, ip2, ip3, ip4, mm, pt1, pt2) \
STMT_BEGIN \
- test_eq(tor_addr_parse_mask_ports(xx, 0, &t1, &mask, &port1, &port2), \
- f); \
+ tt_int_op(tor_addr_parse_mask_ports(xx, 0, &t1, &mask, &port1, &port2), \
+ ==, f); \
p1=tor_inet_ntop(AF_INET6, &t1.addr.in6_addr, bug, sizeof(bug)); \
- test_eq(htonl(ip1), tor_addr_to_in6_addr32(&t1)[0]); \
- test_eq(htonl(ip2), tor_addr_to_in6_addr32(&t1)[1]); \
- test_eq(htonl(ip3), tor_addr_to_in6_addr32(&t1)[2]); \
- test_eq(htonl(ip4), tor_addr_to_in6_addr32(&t1)[3]); \
- test_eq(mask, mm); \
- test_eq(port1, pt1); \
- test_eq(port2, pt2); \
+ tt_int_op(htonl(ip1), ==, tor_addr_to_in6_addr32(&t1)[0]); \
+ tt_int_op(htonl(ip2), ==, tor_addr_to_in6_addr32(&t1)[1]); \
+ tt_int_op(htonl(ip3), ==, tor_addr_to_in6_addr32(&t1)[2]); \
+ tt_int_op(htonl(ip4), ==, tor_addr_to_in6_addr32(&t1)[3]); \
+ tt_int_op(mask, ==, mm); \
+ tt_uint_op(port1, ==, pt1); \
+ tt_uint_op(port2, ==, pt2); \
STMT_END
/** Run unit tests for IPv6 encoding/decoding/manipulation functions. */
static void
-test_addr_ip6_helpers(void)
+test_addr_ip6_helpers(void *arg)
{
char buf[TOR_ADDR_BUF_LEN], bug[TOR_ADDR_BUF_LEN];
char rbuf[REVERSE_LOOKUP_NAME_BUF_LEN];
@@ -194,28 +196,29 @@ test_addr_ip6_helpers(void)
struct sockaddr_in6 *sin6;
/* Test tor_inet_ntop and tor_inet_pton: IPv6 */
+ (void)arg;
{
const char *ip = "2001::1234";
const char *ip_ffff = "::ffff:192.168.1.2";
/* good round trip */
- test_eq(tor_inet_pton(AF_INET6, ip, &a1), 1);
- test_eq_ptr(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), &buf);
- test_streq(buf, ip);
+ tt_int_op(tor_inet_pton(AF_INET6, ip, &a1),==, 1);
+ tt_ptr_op(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)),==, &buf);
+ tt_str_op(buf,==, ip);
/* good round trip - ::ffff:0:0 style */
- test_eq(tor_inet_pton(AF_INET6, ip_ffff, &a2), 1);
- test_eq_ptr(tor_inet_ntop(AF_INET6, &a2, buf, sizeof(buf)), &buf);
- test_streq(buf, ip_ffff);
+ tt_int_op(tor_inet_pton(AF_INET6, ip_ffff, &a2),==, 1);
+ tt_ptr_op(tor_inet_ntop(AF_INET6, &a2, buf, sizeof(buf)),==, &buf);
+ tt_str_op(buf,==, ip_ffff);
/* just long enough buffer (remember \0) */
- test_streq(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)+1), ip);
- test_streq(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)+1),
+ tt_str_op(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)+1),==, ip);
+ tt_str_op(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)+1),==,
ip_ffff);
/* too short buffer (remember \0) */
- test_eq_ptr(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)), NULL);
- test_eq_ptr(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)), NULL);
+ tt_ptr_op(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)),==, NULL);
+ tt_ptr_op(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)),==, NULL);
}
/* ==== Converting to and from sockaddr_t. */
@@ -224,16 +227,16 @@ test_addr_ip6_helpers(void)
sin->sin_port = htons(9090);
sin->sin_addr.s_addr = htonl(0x7f7f0102); /*127.127.1.2*/
tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, &port1);
- test_eq(tor_addr_family(&t1), AF_INET);
- test_eq(tor_addr_to_ipv4h(&t1), 0x7f7f0102);
+ tt_int_op(tor_addr_family(&t1),==, AF_INET);
+ tt_int_op(tor_addr_to_ipv4h(&t1),==, 0x7f7f0102);
tt_int_op(port1, ==, 9090);
memset(&sa_storage, 0, sizeof(sa_storage));
- test_eq(sizeof(struct sockaddr_in),
+ tt_int_op(sizeof(struct sockaddr_in),==,
tor_addr_to_sockaddr(&t1, 1234, (struct sockaddr *)&sa_storage,
sizeof(sa_storage)));
- test_eq(1234, ntohs(sin->sin_port));
- test_eq(0x7f7f0102, ntohl(sin->sin_addr.s_addr));
+ tt_int_op(1234,==, ntohs(sin->sin_port));
+ tt_int_op(0x7f7f0102,==, ntohl(sin->sin_addr.s_addr));
memset(&sa_storage, 0, sizeof(sa_storage));
sin6 = (struct sockaddr_in6 *)&sa_storage;
@@ -241,37 +244,37 @@ test_addr_ip6_helpers(void)
sin6->sin6_port = htons(7070);
sin6->sin6_addr.s6_addr[0] = 128;
tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6, &port1);
- test_eq(tor_addr_family(&t1), AF_INET6);
+ tt_int_op(tor_addr_family(&t1),==, AF_INET6);
tt_int_op(port1, ==, 7070);
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
- test_streq(p1, "8000::");
+ tt_str_op(p1,==, "8000::");
memset(&sa_storage, 0, sizeof(sa_storage));
- test_eq(sizeof(struct sockaddr_in6),
+ tt_int_op(sizeof(struct sockaddr_in6),==,
tor_addr_to_sockaddr(&t1, 9999, (struct sockaddr *)&sa_storage,
sizeof(sa_storage)));
- test_eq(AF_INET6, sin6->sin6_family);
- test_eq(9999, ntohs(sin6->sin6_port));
- test_eq(0x80000000, ntohl(S6_ADDR32(sin6->sin6_addr)[0]));
+ tt_int_op(AF_INET6,==, sin6->sin6_family);
+ tt_int_op(9999,==, ntohs(sin6->sin6_port));
+ tt_int_op(0x80000000,==, ntohl(S6_ADDR32(sin6->sin6_addr)[0]));
/* ==== tor_addr_lookup: static cases. (Can't test dns without knowing we
* have a good resolver. */
- test_eq(0, tor_addr_lookup("127.128.129.130", AF_UNSPEC, &t1));
- test_eq(AF_INET, tor_addr_family(&t1));
- test_eq(tor_addr_to_ipv4h(&t1), 0x7f808182);
+ tt_int_op(0,==, tor_addr_lookup("127.128.129.130", AF_UNSPEC, &t1));
+ tt_int_op(AF_INET,==, tor_addr_family(&t1));
+ tt_int_op(tor_addr_to_ipv4h(&t1),==, 0x7f808182);
- test_eq(0, tor_addr_lookup("9000::5", AF_UNSPEC, &t1));
- test_eq(AF_INET6, tor_addr_family(&t1));
- test_eq(0x90, tor_addr_to_in6_addr8(&t1)[0]);
- test_assert(tor_mem_is_zero((char*)tor_addr_to_in6_addr8(&t1)+1, 14));
- test_eq(0x05, tor_addr_to_in6_addr8(&t1)[15]);
+ tt_int_op(0,==, tor_addr_lookup("9000::5", AF_UNSPEC, &t1));
+ tt_int_op(AF_INET6,==, tor_addr_family(&t1));
+ tt_int_op(0x90,==, tor_addr_to_in6_addr8(&t1)[0]);
+ tt_assert(tor_mem_is_zero((char*)tor_addr_to_in6_addr8(&t1)+1, 14));
+ tt_int_op(0x05,==, tor_addr_to_in6_addr8(&t1)[15]);
/* === Test pton: valid af_inet6 */
/* Simple, valid parsing. */
r = tor_inet_pton(AF_INET6,
"0102:0304:0506:0708:090A:0B0C:0D0E:0F10", &a1);
- test_assert(r==1);
- for (i=0;i<16;++i) { test_eq(i+1, (int)a1.s6_addr[i]); }
+ tt_int_op(r, ==, 1);
+ for (i=0;i<16;++i) { tt_int_op(i+1,==, (int)a1.s6_addr[i]); }
/* ipv4 ending. */
test_pton6_same("0102:0304:0506:0708:090A:0B0C:0D0E:0F10",
"0102:0304:0506:0708:090A:0B0C:13.14.15.16");
@@ -311,7 +314,7 @@ test_addr_ip6_helpers(void)
"1000:1:0:7::");
/* Bad af param */
- test_eq(tor_inet_pton(AF_UNSPEC, 0, 0), -1);
+ tt_int_op(tor_inet_pton(AF_UNSPEC, 0, 0),==, -1);
/* === Test pton: invalid in6. */
test_pton6_bad("foobar.");
@@ -414,10 +417,10 @@ test_addr_ip6_helpers(void)
test_addr_compare("0::ffff:5.2.2.1", <, "::ffff:6.0.0.0"); /* XXXX wrong. */
tor_addr_parse_mask_ports("[::ffff:2.3.4.5]", 0, &t1, NULL, NULL, NULL);
tor_addr_parse_mask_ports("2.3.4.5", 0, &t2, NULL, NULL, NULL);
- test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) == 0);
+ tt_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) == 0);
tor_addr_parse_mask_ports("[::ffff:2.3.4.4]", 0, &t1, NULL, NULL, NULL);
tor_addr_parse_mask_ports("2.3.4.5", 0, &t2, NULL, NULL, NULL);
- test_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) < 0);
+ tt_assert(tor_addr_compare(&t1, &t2, CMP_SEMANTIC) < 0);
/* test compare_masked */
test_addr_compare_masked("ffff::", ==, "ffff::0", 128);
@@ -426,113 +429,113 @@ test_addr_ip6_helpers(void)
test_addr_compare_masked("0::2:2:1", ==, "0::8000:2:1", 80);
/* Test undecorated tor_addr_to_str */
- test_eq(AF_INET6, tor_addr_parse(&t1, "[123:45:6789::5005:11]"));
+ tt_int_op(AF_INET6,==, tor_addr_parse(&t1, "[123:45:6789::5005:11]"));
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
- test_streq(p1, "123:45:6789::5005:11");
- test_eq(AF_INET, tor_addr_parse(&t1, "18.0.0.1"));
+ tt_str_op(p1,==, "123:45:6789::5005:11");
+ tt_int_op(AF_INET,==, tor_addr_parse(&t1, "18.0.0.1"));
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0);
- test_streq(p1, "18.0.0.1");
+ tt_str_op(p1,==, "18.0.0.1");
/* Test decorated tor_addr_to_str */
- test_eq(AF_INET6, tor_addr_parse(&t1, "[123:45:6789::5005:11]"));
+ tt_int_op(AF_INET6,==, tor_addr_parse(&t1, "[123:45:6789::5005:11]"));
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
- test_streq(p1, "[123:45:6789::5005:11]");
- test_eq(AF_INET, tor_addr_parse(&t1, "18.0.0.1"));
+ tt_str_op(p1,==, "[123:45:6789::5005:11]");
+ tt_int_op(AF_INET,==, tor_addr_parse(&t1, "18.0.0.1"));
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
- test_streq(p1, "18.0.0.1");
+ tt_str_op(p1,==, "18.0.0.1");
/* Test buffer bounds checking of tor_addr_to_str */
- test_eq(AF_INET6, tor_addr_parse(&t1, "::")); /* 2 + \0 */
- test_eq_ptr(tor_addr_to_str(buf, &t1, 2, 0), NULL); /* too short buf */
- test_streq(tor_addr_to_str(buf, &t1, 3, 0), "::");
- test_eq_ptr(tor_addr_to_str(buf, &t1, 4, 1), NULL); /* too short buf */
- test_streq(tor_addr_to_str(buf, &t1, 5, 1), "[::]");
-
- test_eq(AF_INET6, tor_addr_parse(&t1, "2000::1337")); /* 10 + \0 */
- test_eq_ptr(tor_addr_to_str(buf, &t1, 10, 0), NULL); /* too short buf */
- test_streq(tor_addr_to_str(buf, &t1, 11, 0), "2000::1337");
- test_eq_ptr(tor_addr_to_str(buf, &t1, 12, 1), NULL); /* too short buf */
- test_streq(tor_addr_to_str(buf, &t1, 13, 1), "[2000::1337]");
-
- test_eq(AF_INET, tor_addr_parse(&t1, "1.2.3.4")); /* 7 + \0 */
- test_eq_ptr(tor_addr_to_str(buf, &t1, 7, 0), NULL); /* too short buf */
- test_streq(tor_addr_to_str(buf, &t1, 8, 0), "1.2.3.4");
-
- test_eq(AF_INET, tor_addr_parse(&t1, "255.255.255.255")); /* 15 + \0 */
- test_eq_ptr(tor_addr_to_str(buf, &t1, 15, 0), NULL); /* too short buf */
- test_streq(tor_addr_to_str(buf, &t1, 16, 0), "255.255.255.255");
- test_eq_ptr(tor_addr_to_str(buf, &t1, 15, 1), NULL); /* too short buf */
- test_streq(tor_addr_to_str(buf, &t1, 16, 1), "255.255.255.255");
+ tt_int_op(AF_INET6,==, tor_addr_parse(&t1, "::")); /* 2 + \0 */
+ tt_ptr_op(tor_addr_to_str(buf, &t1, 2, 0),==, NULL); /* too short buf */
+ tt_str_op(tor_addr_to_str(buf, &t1, 3, 0),==, "::");
+ tt_ptr_op(tor_addr_to_str(buf, &t1, 4, 1),==, NULL); /* too short buf */
+ tt_str_op(tor_addr_to_str(buf, &t1, 5, 1),==, "[::]");
+
+ tt_int_op(AF_INET6,==, tor_addr_parse(&t1, "2000::1337")); /* 10 + \0 */
+ tt_ptr_op(tor_addr_to_str(buf, &t1, 10, 0),==, NULL); /* too short buf */
+ tt_str_op(tor_addr_to_str(buf, &t1, 11, 0),==, "2000::1337");
+ tt_ptr_op(tor_addr_to_str(buf, &t1, 12, 1),==, NULL); /* too short buf */
+ tt_str_op(tor_addr_to_str(buf, &t1, 13, 1),==, "[2000::1337]");
+
+ tt_int_op(AF_INET,==, tor_addr_parse(&t1, "1.2.3.4")); /* 7 + \0 */
+ tt_ptr_op(tor_addr_to_str(buf, &t1, 7, 0),==, NULL); /* too short buf */
+ tt_str_op(tor_addr_to_str(buf, &t1, 8, 0),==, "1.2.3.4");
+
+ tt_int_op(AF_INET,==, tor_addr_parse(&t1, "255.255.255.255")); /* 15 + \0 */
+ tt_ptr_op(tor_addr_to_str(buf, &t1, 15, 0),==, NULL); /* too short buf */
+ tt_str_op(tor_addr_to_str(buf, &t1, 16, 0),==, "255.255.255.255");
+ tt_ptr_op(tor_addr_to_str(buf, &t1, 15, 1),==, NULL); /* too short buf */
+ tt_str_op(tor_addr_to_str(buf, &t1, 16, 1),==, "255.255.255.255");
t1.family = AF_UNSPEC;
- test_eq_ptr(tor_addr_to_str(buf, &t1, sizeof(buf), 0), NULL);
+ tt_ptr_op(tor_addr_to_str(buf, &t1, sizeof(buf), 0),==, NULL);
/* Test tor_addr_parse_PTR_name */
i = tor_addr_parse_PTR_name(&t1, "Foobar.baz", AF_UNSPEC, 0);
- test_eq(0, i);
+ tt_int_op(0,==, i);
i = tor_addr_parse_PTR_name(&t1, "Foobar.baz", AF_UNSPEC, 1);
- test_eq(0, i);
+ tt_int_op(0,==, i);
i = tor_addr_parse_PTR_name(&t1, "9999999999999999999999999999.in-addr.arpa",
AF_UNSPEC, 1);
- test_eq(-1, i);
+ tt_int_op(-1,==, i);
i = tor_addr_parse_PTR_name(&t1, "1.0.168.192.in-addr.arpa",
AF_UNSPEC, 1);
- test_eq(1, i);
- test_eq(tor_addr_family(&t1), AF_INET);
+ tt_int_op(1,==, i);
+ tt_int_op(tor_addr_family(&t1),==, AF_INET);
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
- test_streq(p1, "192.168.0.1");
+ tt_str_op(p1,==, "192.168.0.1");
i = tor_addr_parse_PTR_name(&t1, "192.168.0.99", AF_UNSPEC, 0);
- test_eq(0, i);
+ tt_int_op(0,==, i);
i = tor_addr_parse_PTR_name(&t1, "192.168.0.99", AF_UNSPEC, 1);
- test_eq(1, i);
+ tt_int_op(1,==, i);
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
- test_streq(p1, "192.168.0.99");
+ tt_str_op(p1,==, "192.168.0.99");
memset(&t1, 0, sizeof(t1));
i = tor_addr_parse_PTR_name(&t1,
"0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f."
"f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
"ip6.ARPA",
AF_UNSPEC, 0);
- test_eq(1, i);
+ tt_int_op(1,==, i);
p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1);
- test_streq(p1, "[9dee:effe:ebe1:beef:fedc:ba98:7654:3210]");
+ tt_str_op(p1,==, "[9dee:effe:ebe1:beef:fedc:ba98:7654:3210]");
/* Failing cases. */
i = tor_addr_parse_PTR_name(&t1,
"6.7.8.9.a.b.c.d.e.f."
"f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
"ip6.ARPA",
AF_UNSPEC, 0);
- test_eq(i, -1);
+ tt_int_op(i,==, -1);
i = tor_addr_parse_PTR_name(&t1,
"6.7.8.9.a.b.c.d.e.f.a.b.c.d.e.f.0."
"f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
"ip6.ARPA",
AF_UNSPEC, 0);
- test_eq(i, -1);
+ tt_int_op(i,==, -1);
i = tor_addr_parse_PTR_name(&t1,
"6.7.8.9.a.b.c.d.e.f.X.0.0.0.0.9."
"f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
"ip6.ARPA",
AF_UNSPEC, 0);
- test_eq(i, -1);
+ tt_int_op(i,==, -1);
i = tor_addr_parse_PTR_name(&t1, "32.1.1.in-addr.arpa",
AF_UNSPEC, 0);
- test_eq(i, -1);
+ tt_int_op(i,==, -1);
i = tor_addr_parse_PTR_name(&t1, ".in-addr.arpa",
AF_UNSPEC, 0);
- test_eq(i, -1);
+ tt_int_op(i,==, -1);
i = tor_addr_parse_PTR_name(&t1, "1.2.3.4.5.in-addr.arpa",
AF_UNSPEC, 0);
- test_eq(i, -1);
+ tt_int_op(i,==, -1);
i = tor_addr_parse_PTR_name(&t1, "1.2.3.4.5.in-addr.arpa",
AF_INET6, 0);
- test_eq(i, -1);
+ tt_int_op(i,==, -1);
i = tor_addr_parse_PTR_name(&t1,
"6.7.8.9.a.b.c.d.e.f.a.b.c.d.e.0."
"f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9."
"ip6.ARPA",
AF_INET, 0);
- test_eq(i, -1);
+ tt_int_op(i,==, -1);
/* === Test tor_addr_to_PTR_name */
@@ -544,19 +547,19 @@ test_addr_ip6_helpers(void)
tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, NULL);
/* Check IPv4 PTR - too short buffer */
- test_eq(tor_addr_to_PTR_name(rbuf, 1, &t1), -1);
- test_eq(tor_addr_to_PTR_name(rbuf,
+ tt_int_op(tor_addr_to_PTR_name(rbuf, 1, &t1),==, -1);
+ tt_int_op(tor_addr_to_PTR_name(rbuf,
strlen("3.2.1.127.in-addr.arpa") - 1,
- &t1), -1);
+ &t1),==, -1);
/* Check IPv4 PTR - valid addr */
- test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),
+ tt_int_op(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),==,
strlen("3.2.1.127.in-addr.arpa"));
- test_streq(rbuf, "3.2.1.127.in-addr.arpa");
+ tt_str_op(rbuf,==, "3.2.1.127.in-addr.arpa");
/* Invalid addr family */
t1.family = AF_UNSPEC;
- test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1), -1);
+ tt_int_op(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),==, -1);
/* Stage IPv6 addr */
memset(&sa_storage, 0, sizeof(sa_storage));
@@ -573,114 +576,114 @@ test_addr_ip6_helpers(void)
"0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.ip6.arpa";
/* Check IPv6 PTR - too short buffer */
- test_eq(tor_addr_to_PTR_name(rbuf, 0, &t1), -1);
- test_eq(tor_addr_to_PTR_name(rbuf, strlen(addr_PTR) - 1, &t1), -1);
+ tt_int_op(tor_addr_to_PTR_name(rbuf, 0, &t1),==, -1);
+ tt_int_op(tor_addr_to_PTR_name(rbuf, strlen(addr_PTR) - 1, &t1),==, -1);
/* Check IPv6 PTR - valid addr */
- test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),
+ tt_int_op(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1),==,
strlen(addr_PTR));
- test_streq(rbuf, addr_PTR);
+ tt_str_op(rbuf,==, addr_PTR);
}
/* XXXX turn this into a separate function; it's not all IPv6. */
/* test tor_addr_parse_mask_ports */
test_addr_mask_ports_parse("[::f]/17:47-95", AF_INET6,
0, 0, 0, 0x0000000f, 17, 47, 95);
- test_streq(p1, "::f");
+ tt_str_op(p1,==, "::f");
//test_addr_parse("[::fefe:4.1.1.7/120]:999-1000");
//test_addr_parse_check("::fefe:401:107", 120, 999, 1000);
test_addr_mask_ports_parse("[::ffff:4.1.1.7]/120:443", AF_INET6,
0, 0, 0x0000ffff, 0x04010107, 120, 443, 443);
- test_streq(p1, "::ffff:4.1.1.7");
+ tt_str_op(p1,==, "::ffff:4.1.1.7");
test_addr_mask_ports_parse("[abcd:2::44a:0]:2-65000", AF_INET6,
0xabcd0002, 0, 0, 0x044a0000, 128, 2, 65000);
- test_streq(p1, "abcd:2::44a:0");
+ tt_str_op(p1,==, "abcd:2::44a:0");
/* Try some long addresses. */
r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:1111]",
0, &t1, NULL, NULL, NULL);
- test_assert(r == AF_INET6);
+ tt_assert(r == AF_INET6);
r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:11111]",
0, &t1, NULL, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports("[ffff:1111:1111:1111:1111:1111:1111:1111:1]",
0, &t1, NULL, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports(
"[ffff:1111:1111:1111:1111:1111:1111:ffff:"
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:"
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:"
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]",
0, &t1, NULL, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
/* Try some failing cases. */
r=tor_addr_parse_mask_ports("[fefef::]/112", 0, &t1, NULL, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports("[fefe::/112", 0, &t1, NULL, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports("[fefe::", 0, &t1, NULL, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports("[fefe::X]", 0, &t1, NULL, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports("efef::/112", 0, &t1, NULL, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f::]",0,&t1, NULL, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports("[::f:f:f:f:f:f:f:f]",0,&t1, NULL, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports("[f:f:f:f:f:f:f:f:f]",0,&t1, NULL, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports("[f:f:f:f:f::]/fred",0,&t1,&mask, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports("[f:f:f:f:f::]/255.255.0.0",
0,&t1, NULL, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
/* This one will get rejected because it isn't a pure prefix. */
r=tor_addr_parse_mask_ports("1.1.2.3/255.255.64.0",0,&t1, &mask,NULL,NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
/* Test for V4-mapped address with mask < 96. (arguably not valid) */
r=tor_addr_parse_mask_ports("[::ffff:1.1.2.2/33]",0,&t1, &mask, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports("1.1.2.2/33",0,&t1, &mask, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
/* Try extended wildcard addresses with out TAPMP_EXTENDED_STAR*/
r=tor_addr_parse_mask_ports("*4",0,&t1, &mask, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r=tor_addr_parse_mask_ports("*6",0,&t1, &mask, NULL, NULL);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
#if 0
/* Try a mask with a wildcard. */
r=tor_addr_parse_mask_ports("*/16",0,&t1, &mask, NULL, NULL);
- test_assert(r == -1);
+ tt_assert(r == -1);
r=tor_addr_parse_mask_ports("*4/16",TAPMP_EXTENDED_STAR,
&t1, &mask, NULL, NULL);
- test_assert(r == -1);
+ tt_assert(r == -1);
r=tor_addr_parse_mask_ports("*6/30",TAPMP_EXTENDED_STAR,
&t1, &mask, NULL, NULL);
- test_assert(r == -1);
+ tt_assert(r == -1);
#endif
/* Basic mask tests*/
r=tor_addr_parse_mask_ports("1.1.2.2/31",0,&t1, &mask, NULL, NULL);
- test_assert(r == AF_INET);
+ tt_assert(r == AF_INET);
tt_int_op(mask,==,31);
tt_int_op(tor_addr_family(&t1),==,AF_INET);
tt_int_op(tor_addr_to_ipv4h(&t1),==,0x01010202);
r=tor_addr_parse_mask_ports("3.4.16.032:1-2",0,&t1, &mask, &port1, &port2);
- test_assert(r == AF_INET);
+ tt_assert(r == AF_INET);
tt_int_op(mask,==,32);
tt_int_op(tor_addr_family(&t1),==,AF_INET);
tt_int_op(tor_addr_to_ipv4h(&t1),==,0x03041020);
- test_assert(port1 == 1);
- test_assert(port2 == 2);
+ tt_assert(port1 == 1);
+ tt_assert(port2 == 2);
r=tor_addr_parse_mask_ports("1.1.2.3/255.255.128.0",0,&t1, &mask,NULL,NULL);
- test_assert(r == AF_INET);
+ tt_assert(r == AF_INET);
tt_int_op(mask,==,17);
tt_int_op(tor_addr_family(&t1),==,AF_INET);
tt_int_op(tor_addr_to_ipv4h(&t1),==,0x01010203);
r=tor_addr_parse_mask_ports("[efef::]/112",0,&t1, &mask, &port1, &port2);
- test_assert(r == AF_INET6);
- test_assert(port1 == 1);
- test_assert(port2 == 65535);
+ tt_assert(r == AF_INET6);
+ tt_assert(port1 == 1);
+ tt_assert(port2 == 65535);
/* Try regular wildcard behavior without TAPMP_EXTENDED_STAR */
r=tor_addr_parse_mask_ports("*:80-443",0,&t1,&mask,&port1,&port2);
tt_int_op(r,==,AF_INET); /* Old users of this always get inet */
@@ -715,11 +718,11 @@ test_addr_ip6_helpers(void)
tt_int_op(port2,==,65535);
/* make sure inet address lengths >= max */
- test_assert(INET_NTOA_BUF_LEN >= sizeof("255.255.255.255"));
- test_assert(TOR_ADDR_BUF_LEN >=
+ tt_assert(INET_NTOA_BUF_LEN >= sizeof("255.255.255.255"));
+ tt_assert(TOR_ADDR_BUF_LEN >=
sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"));
- test_assert(sizeof(tor_addr_t) >= sizeof(struct in6_addr));
+ tt_assert(sizeof(tor_addr_t) >= sizeof(struct in6_addr));
/* get interface addresses */
r = get_interface_address6(LOG_DEBUG, AF_INET, &t1);
@@ -736,7 +739,7 @@ test_addr_ip6_helpers(void)
/** Test tor_addr_port_parse(). */
static void
-test_addr_parse(void)
+test_addr_parse(void *arg)
{
int r;
tor_addr_t addr;
@@ -744,89 +747,90 @@ test_addr_parse(void)
uint16_t port = 0;
/* Correct call. */
+ (void)arg;
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.1:1234",
&addr, &port, -1);
- test_assert(r == 0);
+ tt_int_op(r, ==, 0);
tor_addr_to_str(buf, &addr, sizeof(buf), 0);
- test_streq(buf, "192.0.2.1");
- test_eq(port, 1234);
+ tt_str_op(buf,==, "192.0.2.1");
+ tt_int_op(port,==, 1234);
r= tor_addr_port_parse(LOG_DEBUG,
"[::1]:1234",
&addr, &port, -1);
- test_assert(r == 0);
+ tt_int_op(r, ==, 0);
tor_addr_to_str(buf, &addr, sizeof(buf), 0);
- test_streq(buf, "::1");
- test_eq(port, 1234);
+ tt_str_op(buf,==, "::1");
+ tt_int_op(port,==, 1234);
/* Domain name. */
r= tor_addr_port_parse(LOG_DEBUG,
"torproject.org:1234",
&addr, &port, -1);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
/* Only IP. */
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.2",
&addr, &port, -1);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.2",
&addr, &port, 200);
- test_assert(r == 0);
+ tt_int_op(r, ==, 0);
tt_int_op(port,==,200);
r= tor_addr_port_parse(LOG_DEBUG,
"[::1]",
&addr, &port, -1);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r= tor_addr_port_parse(LOG_DEBUG,
"[::1]",
&addr, &port, 400);
- test_assert(r == 0);
+ tt_int_op(r, ==, 0);
tt_int_op(port,==,400);
/* Bad port. */
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.2:66666",
&addr, &port, -1);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.2:66666",
&addr, &port, 200);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
/* Only domain name */
r= tor_addr_port_parse(LOG_DEBUG,
"torproject.org",
&addr, &port, -1);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
r= tor_addr_port_parse(LOG_DEBUG,
"torproject.org",
&addr, &port, 200);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
/* Bad IP address */
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2:1234",
&addr, &port, -1);
- test_assert(r == -1);
+ tt_int_op(r, ==, -1);
/* Make sure that the default port has lower priority than the real
one */
r= tor_addr_port_parse(LOG_DEBUG,
"192.0.2.2:1337",
&addr, &port, 200);
- test_assert(r == 0);
+ tt_int_op(r, ==, 0);
tt_int_op(port,==,1337);
r= tor_addr_port_parse(LOG_DEBUG,
"[::1]:1369",
&addr, &port, 200);
- test_assert(r == 0);
+ tt_int_op(r, ==, 0);
tt_int_op(port,==,1369);
done:
@@ -1047,7 +1051,7 @@ test_addr_make_null(void *data)
}
#define ADDR_LEGACY(name) \
- { #name, legacy_test_helper, 0, &legacy_setup, test_addr_ ## name }
+ { #name, test_addr_ ## name , 0, NULL, NULL }
struct testcase_t addr_tests[] = {
ADDR_LEGACY(basic),
diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c
index f24b80f0b0..3ab3d8d8c0 100644
--- a/src/test/test_buffers.c
+++ b/src/test/test_buffers.c
@@ -27,10 +27,10 @@ test_buffers_basic(void *arg)
* buf_new
****/
if (!(buf = buf_new()))
- test_fail();
+ TT_DIE(("Assertion failed."));
//test_eq(buf_capacity(buf), 4096);
- test_eq(buf_datalen(buf), 0);
+ tt_int_op(buf_datalen(buf),==, 0);
/****
* General pointer frobbing
@@ -40,16 +40,16 @@ test_buffers_basic(void *arg)
}
write_to_buf(str, 256, buf);
write_to_buf(str, 256, buf);
- test_eq(buf_datalen(buf), 512);
+ tt_int_op(buf_datalen(buf),==, 512);
fetch_from_buf(str2, 200, buf);
- test_memeq(str, str2, 200);
- test_eq(buf_datalen(buf), 312);
+ tt_mem_op(str,==, str2, 200);
+ tt_int_op(buf_datalen(buf),==, 312);
memset(str2, 0, sizeof(str2));
fetch_from_buf(str2, 256, buf);
- test_memeq(str+200, str2, 56);
- test_memeq(str, str2+56, 200);
- test_eq(buf_datalen(buf), 56);
+ tt_mem_op(str+200,==, str2, 56);
+ tt_mem_op(str,==, str2+56, 200);
+ tt_int_op(buf_datalen(buf),==, 56);
memset(str2, 0, sizeof(str2));
/* Okay, now we should be 512 bytes into the 4096-byte buffer. If we add
* another 3584 bytes, we hit the end. */
@@ -57,16 +57,16 @@ test_buffers_basic(void *arg)
write_to_buf(str, 256, buf);
}
assert_buf_ok(buf);
- test_eq(buf_datalen(buf), 3896);
+ tt_int_op(buf_datalen(buf),==, 3896);
fetch_from_buf(str2, 56, buf);
- test_eq(buf_datalen(buf), 3840);
- test_memeq(str+200, str2, 56);
+ tt_int_op(buf_datalen(buf),==, 3840);
+ tt_mem_op(str+200,==, str2, 56);
for (j=0;j<15;++j) {
memset(str2, 0, sizeof(str2));
fetch_from_buf(str2, 256, buf);
- test_memeq(str, str2, 256);
+ tt_mem_op(str,==, str2, 256);
}
- test_eq(buf_datalen(buf), 0);
+ tt_int_op(buf_datalen(buf),==, 0);
buf_free(buf);
buf = NULL;
@@ -76,7 +76,7 @@ test_buffers_basic(void *arg)
write_to_buf(str+1, 255, buf);
//test_eq(buf_capacity(buf), 256);
fetch_from_buf(str2, 254, buf);
- test_memeq(str+1, str2, 254);
+ tt_mem_op(str+1,==, str2, 254);
//test_eq(buf_capacity(buf), 256);
assert_buf_ok(buf);
write_to_buf(str, 32, buf);
@@ -85,15 +85,15 @@ test_buffers_basic(void *arg)
write_to_buf(str, 256, buf);
assert_buf_ok(buf);
//test_eq(buf_capacity(buf), 512);
- test_eq(buf_datalen(buf), 33+256);
+ tt_int_op(buf_datalen(buf),==, 33+256);
fetch_from_buf(str2, 33, buf);
- test_eq(*str2, str[255]);
+ tt_int_op(*str2,==, str[255]);
- test_memeq(str2+1, str, 32);
+ tt_mem_op(str2+1,==, str, 32);
//test_eq(buf_capacity(buf), 512);
- test_eq(buf_datalen(buf), 256);
+ tt_int_op(buf_datalen(buf),==, 256);
fetch_from_buf(str2, 256, buf);
- test_memeq(str, str2, 256);
+ tt_mem_op(str,==, str2, 256);
/* now try shrinking: case 1. */
buf_free(buf);
@@ -102,10 +102,10 @@ test_buffers_basic(void *arg)
write_to_buf(str,255, buf);
}
//test_eq(buf_capacity(buf), 33668);
- test_eq(buf_datalen(buf), 17085);
+ tt_int_op(buf_datalen(buf),==, 17085);
for (j=0; j < 40; ++j) {
fetch_from_buf(str2, 255,buf);
- test_memeq(str2, str, 255);
+ tt_mem_op(str2,==, str, 255);
}
/* now try shrinking: case 2. */
@@ -116,7 +116,7 @@ test_buffers_basic(void *arg)
}
for (j=0; j < 20; ++j) {
fetch_from_buf(str2, 255,buf);
- test_memeq(str2, str, 255);
+ tt_mem_op(str2,==, str, 255);
}
for (j=0;j<80;++j) {
write_to_buf(str,255, buf);
@@ -124,7 +124,7 @@ test_buffers_basic(void *arg)
//test_eq(buf_capacity(buf),33668);
for (j=0; j < 120; ++j) {
fetch_from_buf(str2, 255,buf);
- test_memeq(str2, str, 255);
+ tt_mem_op(str2,==, str, 255);
}
/* Move from buf to buf. */
@@ -133,27 +133,27 @@ test_buffers_basic(void *arg)
buf2 = buf_new_with_capacity(4096);
for (j=0;j<100;++j)
write_to_buf(str, 255, buf);
- test_eq(buf_datalen(buf), 25500);
+ tt_int_op(buf_datalen(buf),==, 25500);
for (j=0;j<100;++j) {
r = 10;
move_buf_to_buf(buf2, buf, &r);
- test_eq(r, 0);
+ tt_int_op(r,==, 0);
}
- test_eq(buf_datalen(buf), 24500);
- test_eq(buf_datalen(buf2), 1000);
+ tt_int_op(buf_datalen(buf),==, 24500);
+ tt_int_op(buf_datalen(buf2),==, 1000);
for (j=0;j<3;++j) {
fetch_from_buf(str2, 255, buf2);
- test_memeq(str2, str, 255);
+ tt_mem_op(str2,==, str, 255);
}
r = 8192; /*big move*/
move_buf_to_buf(buf2, buf, &r);
- test_eq(r, 0);
+ tt_int_op(r,==, 0);
r = 30000; /* incomplete move */
move_buf_to_buf(buf2, buf, &r);
- test_eq(r, 13692);
+ tt_int_op(r,==, 13692);
for (j=0;j<97;++j) {
fetch_from_buf(str2, 255, buf2);
- test_memeq(str2, str, 255);
+ tt_mem_op(str2,==, str, 255);
}
buf_free(buf);
buf_free(buf2);
@@ -163,16 +163,16 @@ test_buffers_basic(void *arg)
cp = "Testing. This is a moderately long Testing string.";
for (j = 0; cp[j]; j++)
write_to_buf(cp+j, 1, buf);
- test_eq(0, buf_find_string_offset(buf, "Testing", 7));
- test_eq(1, buf_find_string_offset(buf, "esting", 6));
- test_eq(1, buf_find_string_offset(buf, "est", 3));
- test_eq(39, buf_find_string_offset(buf, "ing str", 7));
- test_eq(35, buf_find_string_offset(buf, "Testing str", 11));
- test_eq(32, buf_find_string_offset(buf, "ng ", 3));
- test_eq(43, buf_find_string_offset(buf, "string.", 7));
- test_eq(-1, buf_find_string_offset(buf, "shrdlu", 6));
- test_eq(-1, buf_find_string_offset(buf, "Testing thing", 13));
- test_eq(-1, buf_find_string_offset(buf, "ngx", 3));
+ tt_int_op(0,==, buf_find_string_offset(buf, "Testing", 7));
+ tt_int_op(1,==, buf_find_string_offset(buf, "esting", 6));
+ tt_int_op(1,==, buf_find_string_offset(buf, "est", 3));
+ tt_int_op(39,==, buf_find_string_offset(buf, "ing str", 7));
+ tt_int_op(35,==, buf_find_string_offset(buf, "Testing str", 11));
+ tt_int_op(32,==, buf_find_string_offset(buf, "ng ", 3));
+ tt_int_op(43,==, buf_find_string_offset(buf, "string.", 7));
+ tt_int_op(-1,==, buf_find_string_offset(buf, "shrdlu", 6));
+ tt_int_op(-1,==, buf_find_string_offset(buf, "Testing thing", 13));
+ tt_int_op(-1,==, buf_find_string_offset(buf, "ngx", 3));
buf_free(buf);
buf = NULL;
@@ -240,16 +240,16 @@ test_buffer_pullup(void *arg)
/* Make room for 3000 bytes in the first chunk, so that the pullup-move code
* can get tested. */
tt_int_op(fetch_from_buf(tmp, 3000, buf), ==, 3000);
- test_memeq(tmp, stuff, 3000);
+ tt_mem_op(tmp,==, stuff, 3000);
buf_pullup(buf, 2048, 0);
assert_buf_ok(buf);
buf_get_first_chunk_data(buf, &cp, &sz);
tt_ptr_op(cp, !=, NULL);
tt_int_op(sz, >=, 2048);
- test_memeq(cp, stuff+3000, 2048);
+ tt_mem_op(cp,==, stuff+3000, 2048);
tt_int_op(3000, ==, buf_datalen(buf));
tt_int_op(fetch_from_buf(tmp, 3000, buf), ==, 0);
- test_memeq(tmp, stuff+3000, 2048);
+ tt_mem_op(tmp,==, stuff+3000, 2048);
buf_free(buf);
@@ -269,16 +269,16 @@ test_buffer_pullup(void *arg)
buf_get_first_chunk_data(buf, &cp, &sz);
tt_ptr_op(cp, !=, NULL);
tt_int_op(sz, >=, 12500);
- test_memeq(cp, stuff, 12500);
+ tt_mem_op(cp,==, stuff, 12500);
tt_int_op(buf_datalen(buf), ==, 16000);
fetch_from_buf(tmp, 12400, buf);
- test_memeq(tmp, stuff, 12400);
+ tt_mem_op(tmp,==, stuff, 12400);
tt_int_op(buf_datalen(buf), ==, 3600);
fetch_from_buf(tmp, 3500, buf);
- test_memeq(tmp, stuff+12400, 3500);
+ tt_mem_op(tmp,==, stuff+12400, 3500);
fetch_from_buf(tmp, 100, buf);
- test_memeq(tmp, stuff+15900, 10);
+ tt_mem_op(tmp,==, stuff+15900, 10);
buf_free(buf);
@@ -292,7 +292,7 @@ test_buffer_pullup(void *arg)
buf_get_first_chunk_data(buf, &cp, &sz);
tt_ptr_op(cp, !=, NULL);
tt_int_op(sz, ==, 7900);
- test_memeq(cp, stuff+100, 7900);
+ tt_mem_op(cp,==, stuff+100, 7900);
buf_free(buf);
buf = NULL;
@@ -335,14 +335,14 @@ test_buffer_copy(void *arg)
tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
tt_int_op(len, ==, generic_buffer_len(buf2));
generic_buffer_get(buf2, b, len);
- test_mem_op(b, ==, s, len);
+ tt_mem_op(b, ==, s, len);
/* Now free buf2 and retry so we can test allocating */
generic_buffer_free(buf2);
buf2 = NULL;
tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
tt_int_op(len, ==, generic_buffer_len(buf2));
generic_buffer_get(buf2, b, len);
- test_mem_op(b, ==, s, len);
+ tt_mem_op(b, ==, s, len);
/* Clear buf for next test */
generic_buffer_get(buf, b, len);
tt_int_op(generic_buffer_len(buf),==,0);
@@ -362,7 +362,7 @@ test_buffer_copy(void *arg)
for (i = 0; i < 256; ++i) {
generic_buffer_get(buf2, b, len+1);
tt_int_op((unsigned char)b[0],==,i);
- test_mem_op(b+1, ==, s, len);
+ tt_mem_op(b+1, ==, s, len);
}
done:
@@ -410,7 +410,7 @@ test_buffer_ext_or_cmd(void *arg)
tt_ptr_op(NULL, !=, cmd);
tt_int_op(0x1021, ==, cmd->cmd);
tt_int_op(6, ==, cmd->len);
- test_mem_op("abcdef", ==, cmd->body, 6);
+ tt_mem_op("abcdef", ==, cmd->body, 6);
tt_int_op(0, ==, generic_buffer_len(buf));
ext_or_cmd_free(cmd);
cmd = NULL;
@@ -422,7 +422,7 @@ test_buffer_ext_or_cmd(void *arg)
tt_ptr_op(NULL, !=, cmd);
tt_int_op(0xffff, ==, cmd->cmd);
tt_int_op(10, ==, cmd->len);
- test_mem_op("loremipsum", ==, cmd->body, 10);
+ tt_mem_op("loremipsum", ==, cmd->body, 10);
tt_int_op(4, ==, generic_buffer_len(buf));
ext_or_cmd_free(cmd);
cmd = NULL;
@@ -436,7 +436,7 @@ test_buffer_ext_or_cmd(void *arg)
tt_ptr_op(NULL, !=, cmd);
tt_int_op(0x1000, ==, cmd->cmd);
tt_int_op(0xffff, ==, cmd->len);
- test_mem_op(tmp, ==, cmd->body, 65535);
+ tt_mem_op(tmp, ==, cmd->body, 65535);
tt_int_op(0, ==, generic_buffer_len(buf));
ext_or_cmd_free(cmd);
cmd = NULL;
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c
index d7f60680c2..995e519163 100644
--- a/src/test/test_cell_formats.c
+++ b/src/test/test_cell_formats.c
@@ -35,11 +35,11 @@ test_cfmt_relay_header(void *arg)
tt_int_op(rh.command, ==, 3);
tt_int_op(rh.recognized, ==, 0);
tt_int_op(rh.stream_id, ==, 0x2122);
- test_mem_op(rh.integrity, ==, "ABCD", 4);
+ tt_mem_op(rh.integrity, ==, "ABCD", 4);
tt_int_op(rh.length, ==, 0x103);
relay_header_pack(hdr_out, &rh);
- test_mem_op(hdr_out, ==, hdr_1, RELAY_HEADER_SIZE);
+ tt_mem_op(hdr_out, ==, hdr_1, RELAY_HEADER_SIZE);
done:
;
@@ -402,10 +402,10 @@ test_cfmt_create_cells(void *arg)
tt_int_op(CELL_CREATE, ==, cc.cell_type);
tt_int_op(ONION_HANDSHAKE_TYPE_TAP, ==, cc.handshake_type);
tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, ==, cc.handshake_len);
- test_memeq(cc.onionskin, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10);
+ tt_mem_op(cc.onionskin,==, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10);
tt_int_op(0, ==, create_cell_format(&cell2, &cc));
tt_int_op(cell.command, ==, cell2.command);
- test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE);
+ tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE);
/* A valid create_fast cell. */
memset(&cell, 0, sizeof(cell));
@@ -417,10 +417,10 @@ test_cfmt_create_cells(void *arg)
tt_int_op(CELL_CREATE_FAST, ==, cc.cell_type);
tt_int_op(ONION_HANDSHAKE_TYPE_FAST, ==, cc.handshake_type);
tt_int_op(CREATE_FAST_LEN, ==, cc.handshake_len);
- test_memeq(cc.onionskin, b, CREATE_FAST_LEN + 10);
+ tt_mem_op(cc.onionskin,==, b, CREATE_FAST_LEN + 10);
tt_int_op(0, ==, create_cell_format(&cell2, &cc));
tt_int_op(cell.command, ==, cell2.command);
- test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE);
+ tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE);
/* A valid create2 cell with a TAP payload */
memset(&cell, 0, sizeof(cell));
@@ -433,10 +433,10 @@ test_cfmt_create_cells(void *arg)
tt_int_op(CELL_CREATE2, ==, cc.cell_type);
tt_int_op(ONION_HANDSHAKE_TYPE_TAP, ==, cc.handshake_type);
tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, ==, cc.handshake_len);
- test_memeq(cc.onionskin, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10);
+ tt_mem_op(cc.onionskin,==, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10);
tt_int_op(0, ==, create_cell_format(&cell2, &cc));
tt_int_op(cell.command, ==, cell2.command);
- test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE);
+ tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE);
/* A valid create2 cell with an ntor payload */
memset(&cell, 0, sizeof(cell));
@@ -450,10 +450,10 @@ test_cfmt_create_cells(void *arg)
tt_int_op(CELL_CREATE2, ==, cc.cell_type);
tt_int_op(ONION_HANDSHAKE_TYPE_NTOR, ==, cc.handshake_type);
tt_int_op(NTOR_ONIONSKIN_LEN, ==, cc.handshake_len);
- test_memeq(cc.onionskin, b, NTOR_ONIONSKIN_LEN + 10);
+ tt_mem_op(cc.onionskin,==, b, NTOR_ONIONSKIN_LEN + 10);
tt_int_op(0, ==, create_cell_format(&cell2, &cc));
tt_int_op(cell.command, ==, cell2.command);
- test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE);
+ tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE);
#else
tt_int_op(-1, ==, create_cell_parse(&cc, &cell));
#endif
@@ -470,10 +470,10 @@ test_cfmt_create_cells(void *arg)
tt_int_op(CELL_CREATE, ==, cc.cell_type);
tt_int_op(ONION_HANDSHAKE_TYPE_NTOR, ==, cc.handshake_type);
tt_int_op(NTOR_ONIONSKIN_LEN, ==, cc.handshake_len);
- test_memeq(cc.onionskin, b, NTOR_ONIONSKIN_LEN + 10);
+ tt_mem_op(cc.onionskin,==, b, NTOR_ONIONSKIN_LEN + 10);
tt_int_op(0, ==, create_cell_format(&cell2, &cc));
tt_int_op(cell.command, ==, cell2.command);
- test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE);
+ tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE);
#else
tt_int_op(-1, ==, create_cell_parse(&cc, &cell));
#endif
@@ -527,10 +527,10 @@ test_cfmt_created_cells(void *arg)
tt_int_op(0, ==, created_cell_parse(&cc, &cell));
tt_int_op(CELL_CREATED, ==, cc.cell_type);
tt_int_op(TAP_ONIONSKIN_REPLY_LEN, ==, cc.handshake_len);
- test_memeq(cc.reply, b, TAP_ONIONSKIN_REPLY_LEN + 10);
+ tt_mem_op(cc.reply,==, b, TAP_ONIONSKIN_REPLY_LEN + 10);
tt_int_op(0, ==, created_cell_format(&cell2, &cc));
tt_int_op(cell.command, ==, cell2.command);
- test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE);
+ tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE);
/* A good CREATED_FAST cell */
memset(&cell, 0, sizeof(cell));
@@ -541,10 +541,10 @@ test_cfmt_created_cells(void *arg)
tt_int_op(0, ==, created_cell_parse(&cc, &cell));
tt_int_op(CELL_CREATED_FAST, ==, cc.cell_type);
tt_int_op(CREATED_FAST_LEN, ==, cc.handshake_len);
- test_memeq(cc.reply, b, CREATED_FAST_LEN + 10);
+ tt_mem_op(cc.reply,==, b, CREATED_FAST_LEN + 10);
tt_int_op(0, ==, created_cell_format(&cell2, &cc));
tt_int_op(cell.command, ==, cell2.command);
- test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE);
+ tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE);
/* A good CREATED2 cell with short reply */
memset(&cell, 0, sizeof(cell));
@@ -556,10 +556,10 @@ test_cfmt_created_cells(void *arg)
tt_int_op(0, ==, created_cell_parse(&cc, &cell));
tt_int_op(CELL_CREATED2, ==, cc.cell_type);
tt_int_op(64, ==, cc.handshake_len);
- test_memeq(cc.reply, b, 80);
+ tt_mem_op(cc.reply,==, b, 80);
tt_int_op(0, ==, created_cell_format(&cell2, &cc));
tt_int_op(cell.command, ==, cell2.command);
- test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE);
+ tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE);
/* A good CREATED2 cell with maximal reply */
memset(&cell, 0, sizeof(cell));
@@ -571,10 +571,10 @@ test_cfmt_created_cells(void *arg)
tt_int_op(0, ==, created_cell_parse(&cc, &cell));
tt_int_op(CELL_CREATED2, ==, cc.cell_type);
tt_int_op(496, ==, cc.handshake_len);
- test_memeq(cc.reply, b, 496);
+ tt_mem_op(cc.reply,==, b, 496);
tt_int_op(0, ==, created_cell_format(&cell2, &cc));
tt_int_op(cell.command, ==, cell2.command);
- test_memeq(cell.payload, cell2.payload, CELL_PAYLOAD_SIZE);
+ tt_mem_op(cell.payload,==, cell2.payload, CELL_PAYLOAD_SIZE);
/* Bogus CREATED2 cell: too long! */
memset(&cell, 0, sizeof(cell));
@@ -620,15 +620,15 @@ test_cfmt_extend_cells(void *arg)
tt_str_op("18.244.0.1", ==, fmt_addr(&ec.orport_ipv4.addr));
tt_int_op(258, ==, ec.orport_ipv4.port);
tt_int_op(AF_UNSPEC, ==, tor_addr_family(&ec.orport_ipv6.addr));
- test_memeq(ec.node_id, "electroencephalogram", 20);
+ tt_mem_op(ec.node_id,==, "electroencephalogram", 20);
tt_int_op(cc->cell_type, ==, CELL_CREATE);
tt_int_op(cc->handshake_type, ==, ONION_HANDSHAKE_TYPE_TAP);
tt_int_op(cc->handshake_len, ==, TAP_ONIONSKIN_CHALLENGE_LEN);
- test_memeq(cc->onionskin, b, TAP_ONIONSKIN_CHALLENGE_LEN+20);
+ tt_mem_op(cc->onionskin,==, b, TAP_ONIONSKIN_CHALLENGE_LEN+20);
tt_int_op(0, ==, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND);
tt_int_op(p2_len, ==, 26+TAP_ONIONSKIN_CHALLENGE_LEN);
- test_memeq(p2, p, RELAY_PAYLOAD_SIZE);
+ tt_mem_op(p2,==, p, RELAY_PAYLOAD_SIZE);
/* Let's do an ntor stuffed in a legacy EXTEND cell */
memset(p, 0, sizeof(p));
@@ -644,15 +644,15 @@ test_cfmt_extend_cells(void *arg)
tt_str_op("18.244.0.1", ==, fmt_addr(&ec.orport_ipv4.addr));
tt_int_op(258, ==, ec.orport_ipv4.port);
tt_int_op(AF_UNSPEC, ==, tor_addr_family(&ec.orport_ipv6.addr));
- test_memeq(ec.node_id, "electroencephalogram", 20);
+ tt_mem_op(ec.node_id,==, "electroencephalogram", 20);
tt_int_op(cc->cell_type, ==, CELL_CREATE2);
tt_int_op(cc->handshake_type, ==, ONION_HANDSHAKE_TYPE_NTOR);
tt_int_op(cc->handshake_len, ==, NTOR_ONIONSKIN_LEN);
- test_memeq(cc->onionskin, b, NTOR_ONIONSKIN_LEN+20);
+ tt_mem_op(cc->onionskin,==, b, NTOR_ONIONSKIN_LEN+20);
tt_int_op(0, ==, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND);
tt_int_op(p2_len, ==, 26+TAP_ONIONSKIN_CHALLENGE_LEN);
- test_memeq(p2, p, RELAY_PAYLOAD_SIZE);
+ tt_mem_op(p2,==, p, RELAY_PAYLOAD_SIZE);
tt_int_op(0, ==, create_cell_format_relayed(&cell, cc));
/* Now let's do a minimal ntor EXTEND2 cell. */
@@ -673,15 +673,15 @@ test_cfmt_extend_cells(void *arg)
tt_str_op("18.244.0.1", ==, fmt_addr(&ec.orport_ipv4.addr));
tt_int_op(61681, ==, ec.orport_ipv4.port);
tt_int_op(AF_UNSPEC, ==, tor_addr_family(&ec.orport_ipv6.addr));
- test_memeq(ec.node_id, "anarchoindividualist", 20);
+ tt_mem_op(ec.node_id,==, "anarchoindividualist", 20);
tt_int_op(cc->cell_type, ==, CELL_CREATE2);
tt_int_op(cc->handshake_type, ==, ONION_HANDSHAKE_TYPE_NTOR);
tt_int_op(cc->handshake_len, ==, NTOR_ONIONSKIN_LEN);
- test_memeq(cc->onionskin, b, NTOR_ONIONSKIN_LEN+20);
+ tt_mem_op(cc->onionskin,==, b, NTOR_ONIONSKIN_LEN+20);
tt_int_op(0, ==, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND2);
tt_int_op(p2_len, ==, 35+NTOR_ONIONSKIN_LEN);
- test_memeq(p2, p, RELAY_PAYLOAD_SIZE);
+ tt_mem_op(p2,==, p, RELAY_PAYLOAD_SIZE);
/* Now let's do a fanciful EXTEND2 cell. */
memset(&ec, 0xff, sizeof(ec));
@@ -706,11 +706,11 @@ test_cfmt_extend_cells(void *arg)
tt_int_op(61681, ==, ec.orport_ipv4.port);
tt_str_op("2002::f0:c51e", ==, fmt_addr(&ec.orport_ipv6.addr));
tt_int_op(4370, ==, ec.orport_ipv6.port);
- test_memeq(ec.node_id, "anthropomorphization", 20);
+ tt_mem_op(ec.node_id,==, "anthropomorphization", 20);
tt_int_op(cc->cell_type, ==, CELL_CREATE2);
tt_int_op(cc->handshake_type, ==, 0x105);
tt_int_op(cc->handshake_len, ==, 99);
- test_memeq(cc->onionskin, b, 99+20);
+ tt_mem_op(cc->onionskin,==, b, 99+20);
tt_int_op(0, ==, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
tt_int_op(p2_cmd, ==, RELAY_COMMAND_EXTEND2);
/* We'll generate it minus the IPv6 address and minus the konami code */
@@ -722,7 +722,7 @@ test_cfmt_extend_cells(void *arg)
"0214616e7468726f706f6d6f727068697a6174696f6e"
/* Now the handshake prologue */
"01050063");
- test_memeq(p2+1+8+22+4, b, 99+20);
+ tt_mem_op(p2+1+8+22+4,==, b, 99+20);
tt_int_op(0, ==, create_cell_format_relayed(&cell, cc));
/* == Now try parsing some junk */
@@ -836,11 +836,11 @@ test_cfmt_extended_cells(void *arg)
tt_int_op(RELAY_COMMAND_EXTENDED, ==, ec.cell_type);
tt_int_op(cc->cell_type, ==, CELL_CREATED);
tt_int_op(cc->handshake_len, ==, TAP_ONIONSKIN_REPLY_LEN);
- test_memeq(cc->reply, b, TAP_ONIONSKIN_REPLY_LEN);
+ tt_mem_op(cc->reply,==, b, TAP_ONIONSKIN_REPLY_LEN);
tt_int_op(0, ==, extended_cell_format(&p2_cmd, &p2_len, p2, &ec));
tt_int_op(RELAY_COMMAND_EXTENDED, ==, p2_cmd);
tt_int_op(TAP_ONIONSKIN_REPLY_LEN, ==, p2_len);
- test_memeq(p2, p, sizeof(p2));
+ tt_mem_op(p2,==, p, sizeof(p2));
/* Try an EXTENDED2 cell */
memset(&ec, 0xff, sizeof(ec));
@@ -853,11 +853,11 @@ test_cfmt_extended_cells(void *arg)
tt_int_op(RELAY_COMMAND_EXTENDED2, ==, ec.cell_type);
tt_int_op(cc->cell_type, ==, CELL_CREATED2);
tt_int_op(cc->handshake_len, ==, 42);
- test_memeq(cc->reply, b, 42+10);
+ tt_mem_op(cc->reply,==, b, 42+10);
tt_int_op(0, ==, extended_cell_format(&p2_cmd, &p2_len, p2, &ec));
tt_int_op(RELAY_COMMAND_EXTENDED2, ==, p2_cmd);
tt_int_op(2+42, ==, p2_len);
- test_memeq(p2, p, sizeof(p2));
+ tt_mem_op(p2,==, p, sizeof(p2));
/* Try an almost-too-long EXTENDED2 cell */
memcpy(p, "\x01\xf0", 2);
diff --git a/src/test/test_cell_queue.c b/src/test/test_cell_queue.c
index 92629823ec..3226f7b973 100644
--- a/src/test/test_cell_queue.c
+++ b/src/test/test_cell_queue.c
@@ -69,15 +69,15 @@ test_cq_manip(void *arg)
pc_tmp = cell_queue_pop(&cq);
tt_int_op(cq.n, ==, 1);
tt_ptr_op(pc_tmp, !=, NULL);
- test_mem_op(pc_tmp->body, ==, "\x12\x34\x56\x78\x0a", 5);
- test_mem_op(pc_tmp->body+5, ==, cell.payload, sizeof(cell.payload));
+ tt_mem_op(pc_tmp->body, ==, "\x12\x34\x56\x78\x0a", 5);
+ tt_mem_op(pc_tmp->body+5, ==, cell.payload, sizeof(cell.payload));
packed_cell_free(pc_tmp);
pc_tmp = cell_queue_pop(&cq);
tt_int_op(cq.n, ==, 0);
tt_ptr_op(pc_tmp, !=, NULL);
- test_mem_op(pc_tmp->body, ==, "\x20\x13\x0a", 3);
- test_mem_op(pc_tmp->body+3, ==, cell.payload, sizeof(cell.payload));
+ tt_mem_op(pc_tmp->body, ==, "\x20\x13\x0a", 3);
+ tt_mem_op(pc_tmp->body+3, ==, cell.payload, sizeof(cell.payload));
packed_cell_free(pc_tmp);
pc_tmp = NULL;
diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c
index 53dcab3302..e752eaf62a 100644
--- a/src/test/test_circuitlist.c
+++ b/src/test/test_circuitlist.c
@@ -251,7 +251,7 @@ test_rend_token_maps(void *arg)
tt_ptr_op(c3->rendinfo, ==, NULL);
tt_ptr_op(c4->rendinfo, !=, NULL);
- test_mem_op(c4->rendinfo, ==, tok3, REND_TOKEN_LEN);
+ tt_mem_op(c4->rendinfo, ==, tok3, REND_TOKEN_LEN);
/* Now clear c4's cookie. */
circuit_set_intro_point_digest(c4, NULL);
diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c
index b9c0436ebf..a3cacc4cc7 100644
--- a/src/test/test_circuitmux.c
+++ b/src/test/test_circuitmux.c
@@ -65,7 +65,7 @@ test_cmux_destroy_cell_queue(void *arg)
pc = cell_queue_pop(cq);
tt_assert(pc);
- test_mem_op(pc->body, ==, "\x00\x00\x00\x64\x04\x0a\x00\x00\x00", 9);
+ tt_mem_op(pc->body, ==, "\x00\x00\x00\x64\x04\x0a\x00\x00\x00", 9);
packed_cell_free(pc);
pc = NULL;
diff --git a/src/test/test_config.c b/src/test/test_config.c
index b35984f761..6a91453e8c 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -53,57 +53,57 @@ test_config_addressmap(void *arg)
/* MapAddress .invalidwildcard.com .torserver.exit - no match */
strlcpy(address, "www.invalidwildcard.com", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
/* MapAddress *invalidasterisk.com .torserver.exit - no match */
strlcpy(address, "www.invalidasterisk.com", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
/* Where no mapping for FQDN match on top-level domain */
/* MapAddress .google.com .torserver.exit */
strlcpy(address, "reader.google.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "reader.torserver.exit");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "reader.torserver.exit");
/* MapAddress *.yahoo.com *.google.com.torserver.exit */
strlcpy(address, "reader.yahoo.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "reader.google.com.torserver.exit");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "reader.google.com.torserver.exit");
/*MapAddress *.cnn.com www.cnn.com */
strlcpy(address, "cnn.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "www.cnn.com");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "www.cnn.com");
/* MapAddress .cn.com www.cnn.com */
strlcpy(address, "www.cn.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "www.cnn.com");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "www.cnn.com");
/* MapAddress ex.com www.cnn.com - no match */
strlcpy(address, "www.ex.com", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
/* MapAddress ey.com *.cnn.com - invalid expression */
strlcpy(address, "ey.com", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
/* Where mapping for FQDN match on FQDN */
strlcpy(address, "www.google.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "3.3.3.3");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "3.3.3.3");
strlcpy(address, "www.torproject.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "1.1.1.1");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "1.1.1.1");
strlcpy(address, "other.torproject.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "this.torproject.org.otherserver.exit");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "this.torproject.org.otherserver.exit");
strlcpy(address, "test.torproject.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "2.2.2.2");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "2.2.2.2");
/* Test a chain of address mappings and the order in which they were added:
"MapAddress www.example.org 4.4.4.4"
@@ -111,17 +111,17 @@ test_config_addressmap(void *arg)
"MapAddress 4.4.4.4 5.5.5.5"
*/
strlcpy(address, "www.example.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "5.5.5.5");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "5.5.5.5");
/* Test infinite address mapping results in no change */
strlcpy(address, "www.infiniteloop.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "www.infiniteloop.org");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "www.infiniteloop.org");
/* Test we don't find false positives */
strlcpy(address, "www.example.com", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
/* Test top-level-domain matching a bit harder */
config_free_lines(get_options_mutable()->AddressMap);
@@ -134,24 +134,24 @@ test_config_addressmap(void *arg)
config_register_addressmaps(get_options());
strlcpy(address, "www.abc.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "www.abc.torserver.exit");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "www.abc.torserver.exit");
strlcpy(address, "www.def.com", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "www.def.torserver.exit");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "www.def.torserver.exit");
strlcpy(address, "www.torproject.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "1.1.1.1");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "1.1.1.1");
strlcpy(address, "test.torproject.org", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "1.1.1.1");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "1.1.1.1");
strlcpy(address, "torproject.net", sizeof(address));
- test_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
- test_streq(address, "2.2.2.2");
+ tt_assert(addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_str_op(address,==, "2.2.2.2");
/* We don't support '*' as a mapping directive */
config_free_lines(get_options_mutable()->AddressMap);
@@ -161,13 +161,13 @@ test_config_addressmap(void *arg)
config_register_addressmaps(get_options());
strlcpy(address, "www.abc.com", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
strlcpy(address, "www.def.net", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
strlcpy(address, "www.torproject.org", sizeof(address));
- test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
+ tt_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL));
#undef addressmap_rewrite
@@ -220,13 +220,13 @@ test_config_check_or_create_data_subdir(void *arg)
// The subdirectory shouldn't exist yet,
// but should be created by the call to check_or_create_data_subdir.
- test_assert(r && (errno == ENOENT));
- test_assert(!check_or_create_data_subdir(subdir));
- test_assert(is_private_dir(subpath));
+ tt_assert(r && (errno == ENOENT));
+ tt_assert(!check_or_create_data_subdir(subdir));
+ tt_assert(is_private_dir(subpath));
// The check should return 0, if the directory already exists
// and is private to the user.
- test_assert(!check_or_create_data_subdir(subdir));
+ tt_assert(!check_or_create_data_subdir(subdir));
r = stat(subpath, &st);
if (r) {
@@ -243,9 +243,9 @@ test_config_check_or_create_data_subdir(void *arg)
// If the directory exists, but its mode is too permissive
// a call to check_or_create_data_subdir should reset the mode.
- test_assert(!is_private_dir(subpath));
- test_assert(!check_or_create_data_subdir(subdir));
- test_assert(is_private_dir(subpath));
+ tt_assert(!is_private_dir(subpath));
+ tt_assert(!check_or_create_data_subdir(subdir));
+ tt_assert(is_private_dir(subpath));
#endif
done:
@@ -291,20 +291,20 @@ test_config_write_to_data_subdir(void *arg)
#endif
// Write attempt shoudl fail, if subdirectory doesn't exist.
- test_assert(write_to_data_subdir(subdir, fname, str, NULL));
- test_assert(! check_or_create_data_subdir(subdir));
+ tt_assert(write_to_data_subdir(subdir, fname, str, NULL));
+ tt_assert(! check_or_create_data_subdir(subdir));
// Content of file after write attempt should be
// equal to the original string.
- test_assert(!write_to_data_subdir(subdir, fname, str, NULL));
+ tt_assert(!write_to_data_subdir(subdir, fname, str, NULL));
cp = read_file_to_str(filepath, 0, NULL);
- test_streq(cp, str);
+ tt_str_op(cp,==, str);
tor_free(cp);
// A second write operation should overwrite the old content.
- test_assert(!write_to_data_subdir(subdir, fname, str, NULL));
+ tt_assert(!write_to_data_subdir(subdir, fname, str, NULL));
cp = read_file_to_str(filepath, 0, NULL);
- test_streq(cp, str);
+ tt_str_op(cp,==, str);
tor_free(cp);
done:
@@ -325,48 +325,48 @@ good_bridge_line_test(const char *string, const char *test_addrport,
{
char *tmp = NULL;
bridge_line_t *bridge_line = parse_bridge_line(string);
- test_assert(bridge_line);
+ tt_assert(bridge_line);
/* test addrport */
tmp = tor_strdup(fmt_addrport(&bridge_line->addr, bridge_line->port));
- test_streq(test_addrport, tmp);
+ tt_str_op(test_addrport,==, tmp);
tor_free(tmp);
/* If we were asked to validate a digest, but we did not get a
digest after parsing, we failed. */
if (test_digest && tor_digest_is_zero(bridge_line->digest))
- test_assert(0);
+ tt_assert(0);
/* If we were not asked to validate a digest, and we got a digest
after parsing, we failed again. */
if (!test_digest && !tor_digest_is_zero(bridge_line->digest))
- test_assert(0);
+ tt_assert(0);
/* If we were asked to validate a digest, and we got a digest after
parsing, make sure it's correct. */
if (test_digest) {
tmp = tor_strdup(hex_str(bridge_line->digest, DIGEST_LEN));
tor_strlower(tmp);
- test_streq(test_digest, tmp);
+ tt_str_op(test_digest,==, tmp);
tor_free(tmp);
}
/* If we were asked to validate a transport name, make sure tha it
matches with the transport name that was parsed. */
if (test_transport && !bridge_line->transport_name)
- test_assert(0);
+ tt_assert(0);
if (!test_transport && bridge_line->transport_name)
- test_assert(0);
+ tt_assert(0);
if (test_transport)
- test_streq(test_transport, bridge_line->transport_name);
+ tt_str_op(test_transport,==, bridge_line->transport_name);
/* Validate the SOCKS argument smartlist. */
if (test_socks_args && !bridge_line->socks_args)
- test_assert(0);
+ tt_assert(0);
if (!test_socks_args && bridge_line->socks_args)
- test_assert(0);
+ tt_assert(0);
if (test_socks_args)
- test_assert(smartlist_strings_eq(test_socks_args,
+ tt_assert(smartlist_strings_eq(test_socks_args,
bridge_line->socks_args));
done:
@@ -382,7 +382,7 @@ bad_bridge_line_test(const char *string)
bridge_line_t *bridge_line = parse_bridge_line(string);
if (bridge_line)
TT_FAIL(("%s was supposed to fail, but it didn't.", string));
- test_assert(!bridge_line);
+ tt_assert(!bridge_line);
done:
bridge_line_free(bridge_line);
@@ -490,18 +490,18 @@ test_config_parse_transport_options_line(void *arg)
{ /* too small line */
options_sl = get_options_from_transport_options_line("valley", NULL);
- test_assert(!options_sl);
+ tt_assert(!options_sl);
}
{ /* no k=v values */
options_sl = get_options_from_transport_options_line("hit it!", NULL);
- test_assert(!options_sl);
+ tt_assert(!options_sl);
}
{ /* correct line, but wrong transport specified */
options_sl =
get_options_from_transport_options_line("trebuchet k=v", "rook");
- test_assert(!options_sl);
+ tt_assert(!options_sl);
}
{ /* correct -- no transport specified */
@@ -512,8 +512,8 @@ test_config_parse_transport_options_line(void *arg)
options_sl =
get_options_from_transport_options_line("rook ladi=dadi weliketo=party",
NULL);
- test_assert(options_sl);
- test_assert(smartlist_strings_eq(options_sl, sl_tmp));
+ tt_assert(options_sl);
+ tt_assert(smartlist_strings_eq(options_sl, sl_tmp));
SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
smartlist_free(sl_tmp);
@@ -531,8 +531,8 @@ test_config_parse_transport_options_line(void *arg)
options_sl =
get_options_from_transport_options_line("rook ladi=dadi weliketo=party",
"rook");
- test_assert(options_sl);
- test_assert(smartlist_strings_eq(options_sl, sl_tmp));
+ tt_assert(options_sl);
+ tt_assert(smartlist_strings_eq(options_sl, sl_tmp));
SMARTLIST_FOREACH(sl_tmp, char *, s, tor_free(s));
smartlist_free(sl_tmp);
sl_tmp = NULL;
@@ -576,7 +576,7 @@ test_config_fix_my_family(void *arg)
TT_FAIL(("options_validate failed: %s", err));
}
- test_streq(options->MyFamily, "$1111111111111111111111111111111111111111, "
+ tt_str_op(options->MyFamily,==, "$1111111111111111111111111111111111111111, "
"$1111111111111111111111111111111111111112, "
"$1111111111111111111111111111111111111113");
diff --git a/src/test/test_containers.c b/src/test/test_containers.c
index d7b7b3cfee..24211dd580 100644
--- a/src/test/test_containers.c
+++ b/src/test/test_containers.c
@@ -29,7 +29,7 @@ compare_strs_for_bsearch_(const void *a, const void **b)
/** Helper: return a tristate based on comparing the strings in *<b>a</b> and
* *<b>b</b>, excluding a's first character, and ignoring case. */
static int
-compare_without_first_ch_(const void *a, const void **b)
+cmp_without_first_(const void *a, const void **b)
{
const char *s1 = a, *s2 = *b;
return strcasecmp(s1+1, s2);
@@ -37,7 +37,7 @@ compare_without_first_ch_(const void *a, const void **b)
/** Run unit tests for basic dynamic-sized array functionality. */
static void
-test_container_smartlist_basic(void)
+test_container_smartlist_basic(void *arg)
{
smartlist_t *sl;
char *v0 = tor_strdup("v0");
@@ -52,6 +52,7 @@ test_container_smartlist_basic(void)
/* XXXX test sort_digests, uniq_strings, uniq_digests */
/* Test smartlist add, del_keeporder, insert, get. */
+ (void)arg;
sl = smartlist_new();
smartlist_add(sl, v1);
smartlist_add(sl, v2);
@@ -61,22 +62,22 @@ test_container_smartlist_basic(void)
smartlist_insert(sl, 1, v22);
smartlist_insert(sl, 0, v0);
smartlist_insert(sl, 5, v555);
- test_eq_ptr(v0, smartlist_get(sl,0));
- test_eq_ptr(v1, smartlist_get(sl,1));
- test_eq_ptr(v22, smartlist_get(sl,2));
- test_eq_ptr(v3, smartlist_get(sl,3));
- test_eq_ptr(v4, smartlist_get(sl,4));
- test_eq_ptr(v555, smartlist_get(sl,5));
+ tt_ptr_op(v0,==, smartlist_get(sl,0));
+ tt_ptr_op(v1,==, smartlist_get(sl,1));
+ tt_ptr_op(v22,==, smartlist_get(sl,2));
+ tt_ptr_op(v3,==, smartlist_get(sl,3));
+ tt_ptr_op(v4,==, smartlist_get(sl,4));
+ tt_ptr_op(v555,==, smartlist_get(sl,5));
/* Try deleting in the middle. */
smartlist_del(sl, 1);
- test_eq_ptr(v555, smartlist_get(sl, 1));
+ tt_ptr_op(v555,==, smartlist_get(sl, 1));
/* Try deleting at the end. */
smartlist_del(sl, 4);
- test_eq(4, smartlist_len(sl));
+ tt_int_op(4,==, smartlist_len(sl));
/* test isin. */
- test_assert(smartlist_contains(sl, v3));
- test_assert(!smartlist_contains(sl, v99));
+ tt_assert(smartlist_contains(sl, v3));
+ tt_assert(!smartlist_contains(sl, v99));
done:
smartlist_free(sl);
@@ -92,198 +93,200 @@ test_container_smartlist_basic(void)
/** Run unit tests for smartlist-of-strings functionality. */
static void
-test_container_smartlist_strings(void)
+test_container_smartlist_strings(void *arg)
{
smartlist_t *sl = smartlist_new();
char *cp=NULL, *cp_alloc=NULL;
size_t sz;
/* Test split and join */
- test_eq(0, smartlist_len(sl));
+ (void)arg;
+ tt_int_op(0,==, smartlist_len(sl));
smartlist_split_string(sl, "abc", ":", 0, 0);
- test_eq(1, smartlist_len(sl));
- test_streq("abc", smartlist_get(sl, 0));
+ tt_int_op(1,==, smartlist_len(sl));
+ tt_str_op("abc",==, smartlist_get(sl, 0));
smartlist_split_string(sl, "a::bc::", "::", 0, 0);
- test_eq(4, smartlist_len(sl));
- test_streq("a", smartlist_get(sl, 1));
- test_streq("bc", smartlist_get(sl, 2));
- test_streq("", smartlist_get(sl, 3));
+ tt_int_op(4,==, smartlist_len(sl));
+ tt_str_op("a",==, smartlist_get(sl, 1));
+ tt_str_op("bc",==, smartlist_get(sl, 2));
+ tt_str_op("",==, smartlist_get(sl, 3));
cp_alloc = smartlist_join_strings(sl, "", 0, NULL);
- test_streq(cp_alloc, "abcabc");
+ tt_str_op(cp_alloc,==, "abcabc");
tor_free(cp_alloc);
cp_alloc = smartlist_join_strings(sl, "!", 0, NULL);
- test_streq(cp_alloc, "abc!a!bc!");
+ tt_str_op(cp_alloc,==, "abc!a!bc!");
tor_free(cp_alloc);
cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL);
- test_streq(cp_alloc, "abcXYaXYbcXY");
+ tt_str_op(cp_alloc,==, "abcXYaXYbcXY");
tor_free(cp_alloc);
cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL);
- test_streq(cp_alloc, "abcXYaXYbcXYXY");
+ tt_str_op(cp_alloc,==, "abcXYaXYbcXYXY");
tor_free(cp_alloc);
cp_alloc = smartlist_join_strings(sl, "", 1, NULL);
- test_streq(cp_alloc, "abcabc");
+ tt_str_op(cp_alloc,==, "abcabc");
tor_free(cp_alloc);
smartlist_split_string(sl, "/def/ /ghijk", "/", 0, 0);
- test_eq(8, smartlist_len(sl));
- test_streq("", smartlist_get(sl, 4));
- test_streq("def", smartlist_get(sl, 5));
- test_streq(" ", smartlist_get(sl, 6));
- test_streq("ghijk", smartlist_get(sl, 7));
+ tt_int_op(8,==, smartlist_len(sl));
+ tt_str_op("",==, smartlist_get(sl, 4));
+ tt_str_op("def",==, smartlist_get(sl, 5));
+ tt_str_op(" ",==, smartlist_get(sl, 6));
+ tt_str_op("ghijk",==, smartlist_get(sl, 7));
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
smartlist_clear(sl);
smartlist_split_string(sl, "a,bbd,cdef", ",", SPLIT_SKIP_SPACE, 0);
- test_eq(3, smartlist_len(sl));
- test_streq("a", smartlist_get(sl,0));
- test_streq("bbd", smartlist_get(sl,1));
- test_streq("cdef", smartlist_get(sl,2));
+ tt_int_op(3,==, smartlist_len(sl));
+ tt_str_op("a",==, smartlist_get(sl,0));
+ tt_str_op("bbd",==, smartlist_get(sl,1));
+ tt_str_op("cdef",==, smartlist_get(sl,2));
smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>",
SPLIT_SKIP_SPACE, 0);
- test_eq(8, smartlist_len(sl));
- test_streq("z", smartlist_get(sl,3));
- test_streq("zhasd", smartlist_get(sl,4));
- test_streq("", smartlist_get(sl,5));
- test_streq("bnud", smartlist_get(sl,6));
- test_streq("", smartlist_get(sl,7));
+ tt_int_op(8,==, smartlist_len(sl));
+ tt_str_op("z",==, smartlist_get(sl,3));
+ tt_str_op("zhasd",==, smartlist_get(sl,4));
+ tt_str_op("",==, smartlist_get(sl,5));
+ tt_str_op("bnud",==, smartlist_get(sl,6));
+ tt_str_op("",==, smartlist_get(sl,7));
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
smartlist_clear(sl);
smartlist_split_string(sl, " ab\tc \td ef ", NULL,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- test_eq(4, smartlist_len(sl));
- test_streq("ab", smartlist_get(sl,0));
- test_streq("c", smartlist_get(sl,1));
- test_streq("d", smartlist_get(sl,2));
- test_streq("ef", smartlist_get(sl,3));
+ tt_int_op(4,==, smartlist_len(sl));
+ tt_str_op("ab",==, smartlist_get(sl,0));
+ tt_str_op("c",==, smartlist_get(sl,1));
+ tt_str_op("d",==, smartlist_get(sl,2));
+ tt_str_op("ef",==, smartlist_get(sl,3));
smartlist_split_string(sl, "ghi\tj", NULL,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- test_eq(6, smartlist_len(sl));
- test_streq("ghi", smartlist_get(sl,4));
- test_streq("j", smartlist_get(sl,5));
+ tt_int_op(6,==, smartlist_len(sl));
+ tt_str_op("ghi",==, smartlist_get(sl,4));
+ tt_str_op("j",==, smartlist_get(sl,5));
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
smartlist_clear(sl);
cp_alloc = smartlist_join_strings(sl, "XY", 0, NULL);
- test_streq(cp_alloc, "");
+ tt_str_op(cp_alloc,==, "");
tor_free(cp_alloc);
cp_alloc = smartlist_join_strings(sl, "XY", 1, NULL);
- test_streq(cp_alloc, "XY");
+ tt_str_op(cp_alloc,==, "XY");
tor_free(cp_alloc);
smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- test_eq(3, smartlist_len(sl));
- test_streq("z", smartlist_get(sl, 0));
- test_streq("zhasd", smartlist_get(sl, 1));
- test_streq("bnud", smartlist_get(sl, 2));
+ tt_int_op(3,==, smartlist_len(sl));
+ tt_str_op("z",==, smartlist_get(sl, 0));
+ tt_str_op("zhasd",==, smartlist_get(sl, 1));
+ tt_str_op("bnud",==, smartlist_get(sl, 2));
smartlist_split_string(sl, " z <> zhasd <> <> bnud<> ", "<>",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
- test_eq(5, smartlist_len(sl));
- test_streq("z", smartlist_get(sl, 3));
- test_streq("zhasd <> <> bnud<>", smartlist_get(sl, 4));
+ tt_int_op(5,==, smartlist_len(sl));
+ tt_str_op("z",==, smartlist_get(sl, 3));
+ tt_str_op("zhasd <> <> bnud<>",==, smartlist_get(sl, 4));
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
smartlist_clear(sl);
smartlist_split_string(sl, "abcd\n", "\n",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- test_eq(1, smartlist_len(sl));
- test_streq("abcd", smartlist_get(sl, 0));
+ tt_int_op(1,==, smartlist_len(sl));
+ tt_str_op("abcd",==, smartlist_get(sl, 0));
smartlist_split_string(sl, "efgh", "\n",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- test_eq(2, smartlist_len(sl));
- test_streq("efgh", smartlist_get(sl, 1));
+ tt_int_op(2,==, smartlist_len(sl));
+ tt_str_op("efgh",==, smartlist_get(sl, 1));
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
smartlist_clear(sl);
/* Test swapping, shuffling, and sorting. */
smartlist_split_string(sl, "the,onion,router,by,arma,and,nickm", ",", 0, 0);
- test_eq(7, smartlist_len(sl));
+ tt_int_op(7,==, smartlist_len(sl));
smartlist_sort(sl, compare_strs_);
cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
- test_streq(cp_alloc,"and,arma,by,nickm,onion,router,the");
+ tt_str_op(cp_alloc,==, "and,arma,by,nickm,onion,router,the");
tor_free(cp_alloc);
smartlist_swap(sl, 1, 5);
cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
- test_streq(cp_alloc,"and,router,by,nickm,onion,arma,the");
+ tt_str_op(cp_alloc,==, "and,router,by,nickm,onion,arma,the");
tor_free(cp_alloc);
smartlist_shuffle(sl);
- test_eq(7, smartlist_len(sl));
- test_assert(smartlist_contains_string(sl, "and"));
- test_assert(smartlist_contains_string(sl, "router"));
- test_assert(smartlist_contains_string(sl, "by"));
- test_assert(smartlist_contains_string(sl, "nickm"));
- test_assert(smartlist_contains_string(sl, "onion"));
- test_assert(smartlist_contains_string(sl, "arma"));
- test_assert(smartlist_contains_string(sl, "the"));
+ tt_int_op(7,==, smartlist_len(sl));
+ tt_assert(smartlist_contains_string(sl, "and"));
+ tt_assert(smartlist_contains_string(sl, "router"));
+ tt_assert(smartlist_contains_string(sl, "by"));
+ tt_assert(smartlist_contains_string(sl, "nickm"));
+ tt_assert(smartlist_contains_string(sl, "onion"));
+ tt_assert(smartlist_contains_string(sl, "arma"));
+ tt_assert(smartlist_contains_string(sl, "the"));
/* Test bsearch. */
smartlist_sort(sl, compare_strs_);
- test_streq("nickm", smartlist_bsearch(sl, "zNicKM",
- compare_without_first_ch_));
- test_streq("and", smartlist_bsearch(sl, " AND", compare_without_first_ch_));
- test_eq_ptr(NULL, smartlist_bsearch(sl, " ANz", compare_without_first_ch_));
+ tt_str_op("nickm",==, smartlist_bsearch(sl, "zNicKM",
+ cmp_without_first_));
+ tt_str_op("and",==,
+ smartlist_bsearch(sl, " AND", cmp_without_first_));
+ tt_ptr_op(NULL,==, smartlist_bsearch(sl, " ANz", cmp_without_first_));
/* Test bsearch_idx */
{
int f;
smartlist_t *tmp = NULL;
- test_eq(0, smartlist_bsearch_idx(sl," aaa",compare_without_first_ch_,&f));
- test_eq(f, 0);
- test_eq(0, smartlist_bsearch_idx(sl," and",compare_without_first_ch_,&f));
- test_eq(f, 1);
- test_eq(1, smartlist_bsearch_idx(sl," arm",compare_without_first_ch_,&f));
- test_eq(f, 0);
- test_eq(1, smartlist_bsearch_idx(sl," arma",compare_without_first_ch_,&f));
- test_eq(f, 1);
- test_eq(2, smartlist_bsearch_idx(sl," armb",compare_without_first_ch_,&f));
- test_eq(f, 0);
- test_eq(7, smartlist_bsearch_idx(sl," zzzz",compare_without_first_ch_,&f));
- test_eq(f, 0);
+ tt_int_op(0,==,smartlist_bsearch_idx(sl," aaa",cmp_without_first_,&f));
+ tt_int_op(f,==, 0);
+ tt_int_op(0,==, smartlist_bsearch_idx(sl," and",cmp_without_first_,&f));
+ tt_int_op(f,==, 1);
+ tt_int_op(1,==, smartlist_bsearch_idx(sl," arm",cmp_without_first_,&f));
+ tt_int_op(f,==, 0);
+ tt_int_op(1,==, smartlist_bsearch_idx(sl," arma",cmp_without_first_,&f));
+ tt_int_op(f,==, 1);
+ tt_int_op(2,==, smartlist_bsearch_idx(sl," armb",cmp_without_first_,&f));
+ tt_int_op(f,==, 0);
+ tt_int_op(7,==, smartlist_bsearch_idx(sl," zzzz",cmp_without_first_,&f));
+ tt_int_op(f,==, 0);
/* Test trivial cases for list of length 0 or 1 */
tmp = smartlist_new();
- test_eq(0, smartlist_bsearch_idx(tmp, "foo",
+ tt_int_op(0,==, smartlist_bsearch_idx(tmp, "foo",
compare_strs_for_bsearch_, &f));
- test_eq(f, 0);
+ tt_int_op(f,==, 0);
smartlist_insert(tmp, 0, (void *)("bar"));
- test_eq(1, smartlist_bsearch_idx(tmp, "foo",
+ tt_int_op(1,==, smartlist_bsearch_idx(tmp, "foo",
compare_strs_for_bsearch_, &f));
- test_eq(f, 0);
- test_eq(0, smartlist_bsearch_idx(tmp, "aaa",
+ tt_int_op(f,==, 0);
+ tt_int_op(0,==, smartlist_bsearch_idx(tmp, "aaa",
compare_strs_for_bsearch_, &f));
- test_eq(f, 0);
- test_eq(0, smartlist_bsearch_idx(tmp, "bar",
+ tt_int_op(f,==, 0);
+ tt_int_op(0,==, smartlist_bsearch_idx(tmp, "bar",
compare_strs_for_bsearch_, &f));
- test_eq(f, 1);
+ tt_int_op(f,==, 1);
/* ... and one for length 2 */
smartlist_insert(tmp, 1, (void *)("foo"));
- test_eq(1, smartlist_bsearch_idx(tmp, "foo",
+ tt_int_op(1,==, smartlist_bsearch_idx(tmp, "foo",
compare_strs_for_bsearch_, &f));
- test_eq(f, 1);
- test_eq(2, smartlist_bsearch_idx(tmp, "goo",
+ tt_int_op(f,==, 1);
+ tt_int_op(2,==, smartlist_bsearch_idx(tmp, "goo",
compare_strs_for_bsearch_, &f));
- test_eq(f, 0);
+ tt_int_op(f,==, 0);
smartlist_free(tmp);
}
/* Test reverse() and pop_last() */
smartlist_reverse(sl);
cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
- test_streq(cp_alloc,"the,router,onion,nickm,by,arma,and");
+ tt_str_op(cp_alloc,==, "the,router,onion,nickm,by,arma,and");
tor_free(cp_alloc);
cp_alloc = smartlist_pop_last(sl);
- test_streq(cp_alloc, "and");
+ tt_str_op(cp_alloc,==, "and");
tor_free(cp_alloc);
- test_eq(smartlist_len(sl), 6);
+ tt_int_op(smartlist_len(sl),==, 6);
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
smartlist_clear(sl);
cp_alloc = smartlist_pop_last(sl);
- test_eq_ptr(cp_alloc, NULL);
+ tt_ptr_op(cp_alloc,==, NULL);
/* Test uniq() */
smartlist_split_string(sl,
@@ -292,16 +295,16 @@ test_container_smartlist_strings(void)
smartlist_sort(sl, compare_strs_);
smartlist_uniq(sl, compare_strs_, tor_free_);
cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
- test_streq(cp_alloc, "50,a,canal,man,noon,panama,plan,radar");
+ tt_str_op(cp_alloc,==, "50,a,canal,man,noon,panama,plan,radar");
tor_free(cp_alloc);
/* Test contains_string, contains_string_case and contains_int_as_string */
- test_assert(smartlist_contains_string(sl, "noon"));
- test_assert(!smartlist_contains_string(sl, "noonoon"));
- test_assert(smartlist_contains_string_case(sl, "nOOn"));
- test_assert(!smartlist_contains_string_case(sl, "nooNooN"));
- test_assert(smartlist_contains_int_as_string(sl, 50));
- test_assert(!smartlist_contains_int_as_string(sl, 60));
+ tt_assert(smartlist_contains_string(sl, "noon"));
+ tt_assert(!smartlist_contains_string(sl, "noonoon"));
+ tt_assert(smartlist_contains_string_case(sl, "nOOn"));
+ tt_assert(!smartlist_contains_string_case(sl, "nooNooN"));
+ tt_assert(smartlist_contains_int_as_string(sl, 50));
+ tt_assert(!smartlist_contains_int_as_string(sl, 60));
/* Test smartlist_choose */
{
@@ -309,7 +312,7 @@ test_container_smartlist_strings(void)
int allsame = 1;
int allin = 1;
void *first = smartlist_choose(sl);
- test_assert(smartlist_contains(sl, first));
+ tt_assert(smartlist_contains(sl, first));
for (i = 0; i < 100; ++i) {
void *second = smartlist_choose(sl);
if (second != first)
@@ -317,8 +320,8 @@ test_container_smartlist_strings(void)
if (!smartlist_contains(sl, second))
allin = 0;
}
- test_assert(!allsame);
- test_assert(allin);
+ tt_assert(!allsame);
+ tt_assert(allin);
}
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
smartlist_clear(sl);
@@ -328,17 +331,17 @@ test_container_smartlist_strings(void)
"Some say the Earth will end in ice and some in fire",
" ", 0, 0);
cp = smartlist_get(sl, 4);
- test_streq(cp, "will");
+ tt_str_op(cp,==, "will");
smartlist_add(sl, cp);
smartlist_remove(sl, cp);
tor_free(cp);
cp_alloc = smartlist_join_strings(sl, ",", 0, NULL);
- test_streq(cp_alloc, "Some,say,the,Earth,fire,end,in,ice,and,some,in");
+ tt_str_op(cp_alloc,==, "Some,say,the,Earth,fire,end,in,ice,and,some,in");
tor_free(cp_alloc);
smartlist_string_remove(sl, "in");
cp_alloc = smartlist_join_strings2(sl, "+XX", 1, 0, &sz);
- test_streq(cp_alloc, "Some+say+the+Earth+fire+end+some+ice+and");
- test_eq((int)sz, 40);
+ tt_str_op(cp_alloc,==, "Some+say+the+Earth+fire+end+some+ice+and");
+ tt_int_op((int)sz,==, 40);
done:
@@ -349,7 +352,7 @@ test_container_smartlist_strings(void)
/** Run unit tests for smartlist set manipulation functions. */
static void
-test_container_smartlist_overlap(void)
+test_container_smartlist_overlap(void *arg)
{
smartlist_t *sl = smartlist_new();
smartlist_t *ints = smartlist_new();
@@ -357,6 +360,7 @@ test_container_smartlist_overlap(void)
smartlist_t *evens = smartlist_new();
smartlist_t *primes = smartlist_new();
int i;
+ (void)arg;
for (i=1; i < 10; i += 2)
smartlist_add(odds, (void*)(uintptr_t)i);
for (i=0; i < 10; i += 2)
@@ -365,7 +369,7 @@ test_container_smartlist_overlap(void)
/* add_all */
smartlist_add_all(ints, odds);
smartlist_add_all(ints, evens);
- test_eq(smartlist_len(ints), 10);
+ tt_int_op(smartlist_len(ints),==, 10);
smartlist_add(primes, (void*)2);
smartlist_add(primes, (void*)3);
@@ -373,24 +377,24 @@ test_container_smartlist_overlap(void)
smartlist_add(primes, (void*)7);
/* overlap */
- test_assert(smartlist_overlap(ints, odds));
- test_assert(smartlist_overlap(odds, primes));
- test_assert(smartlist_overlap(evens, primes));
- test_assert(!smartlist_overlap(odds, evens));
+ tt_assert(smartlist_overlap(ints, odds));
+ tt_assert(smartlist_overlap(odds, primes));
+ tt_assert(smartlist_overlap(evens, primes));
+ tt_assert(!smartlist_overlap(odds, evens));
/* intersect */
smartlist_add_all(sl, odds);
smartlist_intersect(sl, primes);
- test_eq(smartlist_len(sl), 3);
- test_assert(smartlist_contains(sl, (void*)3));
- test_assert(smartlist_contains(sl, (void*)5));
- test_assert(smartlist_contains(sl, (void*)7));
+ tt_int_op(smartlist_len(sl),==, 3);
+ tt_assert(smartlist_contains(sl, (void*)3));
+ tt_assert(smartlist_contains(sl, (void*)5));
+ tt_assert(smartlist_contains(sl, (void*)7));
/* subtract */
smartlist_add_all(sl, primes);
smartlist_subtract(sl, odds);
- test_eq(smartlist_len(sl), 1);
- test_assert(smartlist_contains(sl, (void*)2));
+ tt_int_op(smartlist_len(sl),==, 1);
+ tt_assert(smartlist_contains(sl, (void*)2));
done:
smartlist_free(odds);
@@ -402,31 +406,32 @@ test_container_smartlist_overlap(void)
/** Run unit tests for smartlist-of-digests functions. */
static void
-test_container_smartlist_digests(void)
+test_container_smartlist_digests(void *arg)
{
smartlist_t *sl = smartlist_new();
/* contains_digest */
+ (void)arg;
smartlist_add(sl, tor_memdup("AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN));
smartlist_add(sl, tor_memdup("\00090AAB2AAAAaasdAAAAA", DIGEST_LEN));
smartlist_add(sl, tor_memdup("\00090AAB2AAAAaasdAAAAA", DIGEST_LEN));
- test_eq(0, smartlist_contains_digest(NULL, "AAAAAAAAAAAAAAAAAAAA"));
- test_assert(smartlist_contains_digest(sl, "AAAAAAAAAAAAAAAAAAAA"));
- test_assert(smartlist_contains_digest(sl, "\00090AAB2AAAAaasdAAAAA"));
- test_eq(0, smartlist_contains_digest(sl, "\00090AAB2AAABaasdAAAAA"));
+ tt_int_op(0,==, smartlist_contains_digest(NULL, "AAAAAAAAAAAAAAAAAAAA"));
+ tt_assert(smartlist_contains_digest(sl, "AAAAAAAAAAAAAAAAAAAA"));
+ tt_assert(smartlist_contains_digest(sl, "\00090AAB2AAAAaasdAAAAA"));
+ tt_int_op(0,==, smartlist_contains_digest(sl, "\00090AAB2AAABaasdAAAAA"));
/* sort digests */
smartlist_sort_digests(sl);
- test_memeq(smartlist_get(sl, 0), "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN);
- test_memeq(smartlist_get(sl, 1), "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN);
- test_memeq(smartlist_get(sl, 2), "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN);
- test_eq(3, smartlist_len(sl));
+ tt_mem_op(smartlist_get(sl, 0),==, "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN);
+ tt_mem_op(smartlist_get(sl, 1),==, "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN);
+ tt_mem_op(smartlist_get(sl, 2),==, "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN);
+ tt_int_op(3,==, smartlist_len(sl));
/* uniq_digests */
smartlist_uniq_digests(sl);
- test_eq(2, smartlist_len(sl));
- test_memeq(smartlist_get(sl, 0), "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN);
- test_memeq(smartlist_get(sl, 1), "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN);
+ tt_int_op(2,==, smartlist_len(sl));
+ tt_mem_op(smartlist_get(sl, 0),==, "\00090AAB2AAAAaasdAAAAA", DIGEST_LEN);
+ tt_mem_op(smartlist_get(sl, 1),==, "AAAAAAAAAAAAAAAAAAAA", DIGEST_LEN);
done:
SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
@@ -435,13 +440,14 @@ test_container_smartlist_digests(void)
/** Run unit tests for concatenate-a-smartlist-of-strings functions. */
static void
-test_container_smartlist_join(void)
+test_container_smartlist_join(void *arg)
{
smartlist_t *sl = smartlist_new();
smartlist_t *sl2 = smartlist_new(), *sl3 = smartlist_new(),
*sl4 = smartlist_new();
char *joined=NULL;
/* unique, sorted. */
+ (void)arg;
smartlist_split_string(sl,
"Abashments Ambush Anchorman Bacon Banks Borscht "
"Bunks Inhumane Insurance Knish Know Manners "
@@ -457,21 +463,21 @@ test_container_smartlist_join(void)
sl2, char *, cp2,
strcmp(cp1,cp2),
smartlist_add(sl3, cp2)) {
- test_streq(cp1, cp2);
+ tt_str_op(cp1,==, cp2);
smartlist_add(sl4, cp1);
} SMARTLIST_FOREACH_JOIN_END(cp1, cp2);
SMARTLIST_FOREACH(sl3, const char *, cp,
- test_assert(smartlist_contains(sl2, cp) &&
+ tt_assert(smartlist_contains(sl2, cp) &&
!smartlist_contains_string(sl, cp)));
SMARTLIST_FOREACH(sl4, const char *, cp,
- test_assert(smartlist_contains(sl, cp) &&
+ tt_assert(smartlist_contains(sl, cp) &&
smartlist_contains_string(sl2, cp)));
joined = smartlist_join_strings(sl3, ",", 0, NULL);
- test_streq(joined, "Anemias,Anemias,Crossbowmen,Work");
+ tt_str_op(joined,==, "Anemias,Anemias,Crossbowmen,Work");
tor_free(joined);
joined = smartlist_join_strings(sl4, ",", 0, NULL);
- test_streq(joined, "Ambush,Anchorman,Anchorman,Bacon,Inhumane,Insurance,"
+ tt_str_op(joined,==, "Ambush,Anchorman,Anchorman,Bacon,Inhumane,Insurance,"
"Knish,Know,Manners,Manners,Maraschinos,Wombats,Wombats");
tor_free(joined);
@@ -532,18 +538,19 @@ test_container_smartlist_ints_eq(void *arg)
/** Run unit tests for bitarray code */
static void
-test_container_bitarray(void)
+test_container_bitarray(void *arg)
{
bitarray_t *ba = NULL;
int i, j, ok=1;
+ (void)arg;
ba = bitarray_init_zero(1);
- test_assert(ba);
- test_assert(! bitarray_is_set(ba, 0));
+ tt_assert(ba);
+ tt_assert(! bitarray_is_set(ba, 0));
bitarray_set(ba, 0);
- test_assert(bitarray_is_set(ba, 0));
+ tt_assert(bitarray_is_set(ba, 0));
bitarray_clear(ba, 0);
- test_assert(! bitarray_is_set(ba, 0));
+ tt_assert(! bitarray_is_set(ba, 0));
bitarray_free(ba);
ba = bitarray_init_zero(1023);
@@ -558,7 +565,7 @@ test_container_bitarray(void)
if (!bool_eq(bitarray_is_set(ba, j), j%i))
ok = 0;
}
- test_assert(ok);
+ tt_assert(ok);
if (i < 7)
++i;
else if (i == 28)
@@ -575,7 +582,7 @@ test_container_bitarray(void)
/** Run unit tests for digest set code (implemented as a hashtable or as a
* bloom filter) */
static void
-test_container_digestset(void)
+test_container_digestset(void *arg)
{
smartlist_t *included = smartlist_new();
char d[DIGEST_LEN];
@@ -584,6 +591,7 @@ test_container_digestset(void)
int false_positives = 0;
digestset_t *set = NULL;
+ (void)arg;
for (i = 0; i < 1000; ++i) {
crypto_rand(d, DIGEST_LEN);
smartlist_add(included, tor_memdup(d, DIGEST_LEN));
@@ -592,19 +600,19 @@ test_container_digestset(void)
SMARTLIST_FOREACH(included, const char *, cp,
if (digestset_contains(set, cp))
ok = 0);
- test_assert(ok);
+ tt_assert(ok);
SMARTLIST_FOREACH(included, const char *, cp,
digestset_add(set, cp));
SMARTLIST_FOREACH(included, const char *, cp,
if (!digestset_contains(set, cp))
ok = 0);
- test_assert(ok);
+ tt_assert(ok);
for (i = 0; i < 1000; ++i) {
crypto_rand(d, DIGEST_LEN);
if (digestset_contains(set, d))
++false_positives;
}
- test_assert(false_positives < 50); /* Should be far lower. */
+ tt_int_op(50, >, false_positives); /* Should be far lower. */
done:
if (set)
@@ -628,7 +636,7 @@ compare_strings_for_pqueue_(const void *p1, const void *p2)
/** Run unit tests for heap-based priority queue functions. */
static void
-test_container_pqueue(void)
+test_container_pqueue(void *arg)
{
smartlist_t *sl = smartlist_new();
int (*cmp)(const void *, const void*);
@@ -650,6 +658,8 @@ test_container_pqueue(void)
#define OK() smartlist_pqueue_assert_ok(sl, cmp, offset)
+ (void)arg;
+
cmp = compare_strings_for_pqueue_;
smartlist_pqueue_add(sl, cmp, offset, &cows);
smartlist_pqueue_add(sl, cmp, offset, &zebras);
@@ -665,31 +675,31 @@ test_container_pqueue(void)
OK();
- test_eq(smartlist_len(sl), 11);
- test_eq_ptr(smartlist_get(sl, 0), &apples);
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &apples);
- test_eq(smartlist_len(sl), 10);
+ tt_int_op(smartlist_len(sl),==, 11);
+ tt_ptr_op(smartlist_get(sl, 0),==, &apples);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &apples);
+ tt_int_op(smartlist_len(sl),==, 10);
OK();
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &cows);
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &daschunds);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &cows);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &daschunds);
smartlist_pqueue_add(sl, cmp, offset, &chinchillas);
OK();
smartlist_pqueue_add(sl, cmp, offset, &fireflies);
OK();
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &chinchillas);
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &eggplants);
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &fireflies);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &chinchillas);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &eggplants);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &fireflies);
OK();
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &fish);
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &frogs);
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &lobsters);
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &roquefort);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &fish);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &frogs);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &lobsters);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &roquefort);
OK();
- test_eq(smartlist_len(sl), 3);
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &squid);
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &weissbier);
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &zebras);
- test_eq(smartlist_len(sl), 0);
+ tt_int_op(smartlist_len(sl),==, 3);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &squid);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &weissbier);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &zebras);
+ tt_int_op(smartlist_len(sl),==, 0);
OK();
/* Now test remove. */
@@ -699,21 +709,21 @@ test_container_pqueue(void)
smartlist_pqueue_add(sl, cmp, offset, &apples);
smartlist_pqueue_add(sl, cmp, offset, &squid);
smartlist_pqueue_add(sl, cmp, offset, &zebras);
- test_eq(smartlist_len(sl), 6);
+ tt_int_op(smartlist_len(sl),==, 6);
OK();
smartlist_pqueue_remove(sl, cmp, offset, &zebras);
- test_eq(smartlist_len(sl), 5);
+ tt_int_op(smartlist_len(sl),==, 5);
OK();
smartlist_pqueue_remove(sl, cmp, offset, &cows);
- test_eq(smartlist_len(sl), 4);
+ tt_int_op(smartlist_len(sl),==, 4);
OK();
smartlist_pqueue_remove(sl, cmp, offset, &apples);
- test_eq(smartlist_len(sl), 3);
+ tt_int_op(smartlist_len(sl),==, 3);
OK();
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &fish);
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &frogs);
- test_eq_ptr(smartlist_pqueue_pop(sl, cmp, offset), &squid);
- test_eq(smartlist_len(sl), 0);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &fish);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &frogs);
+ tt_ptr_op(smartlist_pqueue_pop(sl, cmp, offset),==, &squid);
+ tt_int_op(smartlist_len(sl),==, 0);
OK();
#undef OK
@@ -725,7 +735,7 @@ test_container_pqueue(void)
/** Run unit tests for string-to-void* map functions */
static void
-test_container_strmap(void)
+test_container_strmap(void *arg)
{
strmap_t *map;
strmap_iter_t *iter;
@@ -742,32 +752,33 @@ test_container_strmap(void)
char *v104 = tor_strdup("v104");
char *v105 = tor_strdup("v105");
+ (void)arg;
map = strmap_new();
- test_assert(map);
- test_eq(strmap_size(map), 0);
- test_assert(strmap_isempty(map));
+ tt_assert(map);
+ tt_int_op(strmap_size(map),==, 0);
+ tt_assert(strmap_isempty(map));
v = strmap_set(map, "K1", v99);
- test_eq_ptr(v, NULL);
- test_assert(!strmap_isempty(map));
+ tt_ptr_op(v,==, NULL);
+ tt_assert(!strmap_isempty(map));
v = strmap_set(map, "K2", v101);
- test_eq_ptr(v, NULL);
+ tt_ptr_op(v,==, NULL);
v = strmap_set(map, "K1", v100);
- test_eq_ptr(v, v99);
- test_eq_ptr(strmap_get(map,"K1"), v100);
- test_eq_ptr(strmap_get(map,"K2"), v101);
- test_eq_ptr(strmap_get(map,"K-not-there"), NULL);
+ tt_ptr_op(v,==, v99);
+ tt_ptr_op(strmap_get(map,"K1"),==, v100);
+ tt_ptr_op(strmap_get(map,"K2"),==, v101);
+ tt_ptr_op(strmap_get(map,"K-not-there"),==, NULL);
strmap_assert_ok(map);
v = strmap_remove(map,"K2");
strmap_assert_ok(map);
- test_eq_ptr(v, v101);
- test_eq_ptr(strmap_get(map,"K2"), NULL);
- test_eq_ptr(strmap_remove(map,"K2"), NULL);
+ tt_ptr_op(v,==, v101);
+ tt_ptr_op(strmap_get(map,"K2"),==, NULL);
+ tt_ptr_op(strmap_remove(map,"K2"),==, NULL);
strmap_set(map, "K2", v101);
strmap_set(map, "K3", v102);
strmap_set(map, "K4", v103);
- test_eq(strmap_size(map), 4);
+ tt_int_op(strmap_size(map),==, 4);
strmap_assert_ok(map);
strmap_set(map, "K5", v104);
strmap_set(map, "K6", v105);
@@ -779,7 +790,7 @@ test_container_strmap(void)
while (!strmap_iter_done(iter)) {
strmap_iter_get(iter,&k,&v);
smartlist_add(found_keys, tor_strdup(k));
- test_eq_ptr(v, strmap_get(map, k));
+ tt_ptr_op(v,==, strmap_get(map, k));
if (!strcmp(k, "K2")) {
iter = strmap_iter_next_rmv(map,iter);
@@ -789,12 +800,12 @@ test_container_strmap(void)
}
/* Make sure we removed K2, but not the others. */
- test_eq_ptr(strmap_get(map, "K2"), NULL);
- test_eq_ptr(strmap_get(map, "K5"), v104);
+ tt_ptr_op(strmap_get(map, "K2"),==, NULL);
+ tt_ptr_op(strmap_get(map, "K5"),==, v104);
/* Make sure we visited everyone once */
smartlist_sort_strings(found_keys);
visited = smartlist_join_strings(found_keys, ":", 0, NULL);
- test_streq(visited, "K1:K2:K3:K4:K5:K6");
+ tt_str_op(visited,==, "K1:K2:K3:K4:K5:K6");
strmap_assert_ok(map);
/* Clean up after ourselves. */
@@ -804,13 +815,13 @@ test_container_strmap(void)
/* Now try some lc functions. */
map = strmap_new();
strmap_set_lc(map,"Ab.C", v1);
- test_eq_ptr(strmap_get(map,"ab.c"), v1);
+ tt_ptr_op(strmap_get(map,"ab.c"),==, v1);
strmap_assert_ok(map);
- test_eq_ptr(strmap_get_lc(map,"AB.C"), v1);
- test_eq_ptr(strmap_get(map,"AB.C"), NULL);
- test_eq_ptr(strmap_remove_lc(map,"aB.C"), v1);
+ tt_ptr_op(strmap_get_lc(map,"AB.C"),==, v1);
+ tt_ptr_op(strmap_get(map,"AB.C"),==, NULL);
+ tt_ptr_op(strmap_remove_lc(map,"aB.C"),==, v1);
strmap_assert_ok(map);
- test_eq_ptr(strmap_get_lc(map,"AB.C"), NULL);
+ tt_ptr_op(strmap_get_lc(map,"AB.C"),==, NULL);
done:
if (map)
@@ -832,7 +843,7 @@ test_container_strmap(void)
/** Run unit tests for getting the median of a list. */
static void
-test_container_order_functions(void)
+test_container_order_functions(void *arg)
{
int lst[25], n = 0;
unsigned int lst2[25];
@@ -840,42 +851,43 @@ test_container_order_functions(void)
#define median() median_int(lst, n)
+ (void)arg;
lst[n++] = 12;
- test_eq(12, median()); /* 12 */
+ tt_int_op(12,==, median()); /* 12 */
lst[n++] = 77;
//smartlist_shuffle(sl);
- test_eq(12, median()); /* 12, 77 */
+ tt_int_op(12,==, median()); /* 12, 77 */
lst[n++] = 77;
//smartlist_shuffle(sl);
- test_eq(77, median()); /* 12, 77, 77 */
+ tt_int_op(77,==, median()); /* 12, 77, 77 */
lst[n++] = 24;
- test_eq(24, median()); /* 12,24,77,77 */
+ tt_int_op(24,==, median()); /* 12,24,77,77 */
lst[n++] = 60;
lst[n++] = 12;
lst[n++] = 25;
//smartlist_shuffle(sl);
- test_eq(25, median()); /* 12,12,24,25,60,77,77 */
+ tt_int_op(25,==, median()); /* 12,12,24,25,60,77,77 */
#undef median
#define third_quartile() third_quartile_uint32(lst2, n)
n = 0;
lst2[n++] = 1;
- test_eq(1, third_quartile()); /* ~1~ */
+ tt_int_op(1,==, third_quartile()); /* ~1~ */
lst2[n++] = 2;
- test_eq(2, third_quartile()); /* 1, ~2~ */
+ tt_int_op(2,==, third_quartile()); /* 1, ~2~ */
lst2[n++] = 3;
lst2[n++] = 4;
lst2[n++] = 5;
- test_eq(4, third_quartile()); /* 1, 2, 3, ~4~, 5 */
+ tt_int_op(4,==, third_quartile()); /* 1, 2, 3, ~4~, 5 */
lst2[n++] = 6;
lst2[n++] = 7;
lst2[n++] = 8;
lst2[n++] = 9;
- test_eq(7, third_quartile()); /* 1, 2, 3, 4, 5, 6, ~7~, 8, 9 */
+ tt_int_op(7,==, third_quartile()); /* 1, 2, 3, 4, 5, 6, ~7~, 8, 9 */
lst2[n++] = 10;
lst2[n++] = 11;
- test_eq(9, third_quartile()); /* 1, 2, 3, 4, 5, 6, 7, 8, ~9~, 10, 11 */
+ tt_int_op(9,==, third_quartile()); /* 1, 2, 3, 4, 5, 6, 7, 8, ~9~, 10, 11 */
#undef third_quartile
@@ -929,7 +941,7 @@ test_container_di_map(void *arg)
/** Run unit tests for fp_pair-to-void* map functions */
static void
-test_container_fp_pair_map(void)
+test_container_fp_pair_map(void *arg)
{
fp_pair_map_t *map;
fp_pair_t fp1, fp2, fp3, fp4, fp5, fp6;
@@ -944,10 +956,11 @@ test_container_fp_pair_map(void)
char *v104 = tor_strdup("v104");
char *v105 = tor_strdup("v105");
+ (void)arg;
map = fp_pair_map_new();
- test_assert(map);
- test_eq(fp_pair_map_size(map), 0);
- test_assert(fp_pair_map_isempty(map));
+ tt_assert(map);
+ tt_int_op(fp_pair_map_size(map),==, 0);
+ tt_assert(fp_pair_map_isempty(map));
memset(fp1.first, 0x11, DIGEST_LEN);
memset(fp1.second, 0x12, DIGEST_LEN);
@@ -964,26 +977,26 @@ test_container_fp_pair_map(void)
v = fp_pair_map_set(map, &fp1, v99);
tt_ptr_op(v, ==, NULL);
- test_assert(!fp_pair_map_isempty(map));
+ tt_assert(!fp_pair_map_isempty(map));
v = fp_pair_map_set(map, &fp2, v101);
tt_ptr_op(v, ==, NULL);
v = fp_pair_map_set(map, &fp1, v100);
tt_ptr_op(v, ==, v99);
- test_eq_ptr(fp_pair_map_get(map, &fp1), v100);
- test_eq_ptr(fp_pair_map_get(map, &fp2), v101);
- test_eq_ptr(fp_pair_map_get(map, &fp3), NULL);
+ tt_ptr_op(fp_pair_map_get(map, &fp1),==, v100);
+ tt_ptr_op(fp_pair_map_get(map, &fp2),==, v101);
+ tt_ptr_op(fp_pair_map_get(map, &fp3),==, NULL);
fp_pair_map_assert_ok(map);
v = fp_pair_map_remove(map, &fp2);
fp_pair_map_assert_ok(map);
- test_eq_ptr(v, v101);
- test_eq_ptr(fp_pair_map_get(map, &fp2), NULL);
- test_eq_ptr(fp_pair_map_remove(map, &fp2), NULL);
+ tt_ptr_op(v,==, v101);
+ tt_ptr_op(fp_pair_map_get(map, &fp2),==, NULL);
+ tt_ptr_op(fp_pair_map_remove(map, &fp2),==, NULL);
fp_pair_map_set(map, &fp2, v101);
fp_pair_map_set(map, &fp3, v102);
fp_pair_map_set(map, &fp4, v103);
- test_eq(fp_pair_map_size(map), 4);
+ tt_int_op(fp_pair_map_size(map),==, 4);
fp_pair_map_assert_ok(map);
fp_pair_map_set(map, &fp5, v104);
fp_pair_map_set(map, &fp6, v105);
@@ -993,7 +1006,7 @@ test_container_fp_pair_map(void)
iter = fp_pair_map_iter_init(map);
while (!fp_pair_map_iter_done(iter)) {
fp_pair_map_iter_get(iter, &k, &v);
- test_eq_ptr(v, fp_pair_map_get(map, &k));
+ tt_ptr_op(v,==, fp_pair_map_get(map, &k));
if (tor_memeq(&fp2, &k, sizeof(fp2))) {
iter = fp_pair_map_iter_next_rmv(map, iter);
@@ -1003,8 +1016,8 @@ test_container_fp_pair_map(void)
}
/* Make sure we removed fp2, but not the others. */
- test_eq_ptr(fp_pair_map_get(map, &fp2), NULL);
- test_eq_ptr(fp_pair_map_get(map, &fp5), v104);
+ tt_ptr_op(fp_pair_map_get(map, &fp2),==, NULL);
+ tt_ptr_op(fp_pair_map_get(map, &fp5),==, v104);
fp_pair_map_assert_ok(map);
/* Clean up after ourselves. */
@@ -1024,7 +1037,7 @@ test_container_fp_pair_map(void)
}
#define CONTAINER_LEGACY(name) \
- { #name, legacy_test_helper, 0, &legacy_setup, test_container_ ## name }
+ { #name, test_container_ ## name , 0, NULL, NULL }
#define CONTAINER(name, flags) \
{ #name, test_container_ ## name, (flags), NULL, NULL }
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 5d8edb6550..795c603fd4 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -5,6 +5,7 @@
#include "orconfig.h"
#define CRYPTO_CURVE25519_PRIVATE
+#define CRYPTO_S2K_PRIVATE
#include "or.h"
#include "test.h"
#include "aes.h"
@@ -13,6 +14,10 @@
#ifdef CURVE25519_ENABLED
#include "crypto_curve25519.h"
#endif
+#include "crypto_ed25519.h"
+#include "ed25519_vectors.inc"
+#include "crypto_s2k.h"
+#include "crypto_pwbox.h"
extern const char AUTHORITY_SIGNKEY_3[];
extern const char AUTHORITY_SIGNKEY_A_DIGEST[];
@@ -20,7 +25,7 @@ extern const char AUTHORITY_SIGNKEY_A_DIGEST256[];
/** Run unit tests for Diffie-Hellman functionality. */
static void
-test_crypto_dh(void)
+test_crypto_dh(void *arg)
{
crypto_dh_t *dh1 = crypto_dh_new(DH_TYPE_CIRCUIT);
crypto_dh_t *dh2 = crypto_dh_new(DH_TYPE_CIRCUIT);
@@ -30,24 +35,25 @@ test_crypto_dh(void)
char s2[DH_BYTES];
ssize_t s1len, s2len;
- test_eq(crypto_dh_get_bytes(dh1), DH_BYTES);
- test_eq(crypto_dh_get_bytes(dh2), DH_BYTES);
+ (void)arg;
+ tt_int_op(crypto_dh_get_bytes(dh1),==, DH_BYTES);
+ tt_int_op(crypto_dh_get_bytes(dh2),==, DH_BYTES);
memset(p1, 0, DH_BYTES);
memset(p2, 0, DH_BYTES);
- test_memeq(p1, p2, DH_BYTES);
- test_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES));
- test_memneq(p1, p2, DH_BYTES);
- test_assert(! crypto_dh_get_public(dh2, p2, DH_BYTES));
- test_memneq(p1, p2, DH_BYTES);
+ tt_mem_op(p1,==, p2, DH_BYTES);
+ tt_assert(! crypto_dh_get_public(dh1, p1, DH_BYTES));
+ tt_mem_op(p1,!=, p2, DH_BYTES);
+ tt_assert(! crypto_dh_get_public(dh2, p2, DH_BYTES));
+ tt_mem_op(p1,!=, p2, DH_BYTES);
memset(s1, 0, DH_BYTES);
memset(s2, 0xFF, DH_BYTES);
s1len = crypto_dh_compute_secret(LOG_WARN, dh1, p2, DH_BYTES, s1, 50);
s2len = crypto_dh_compute_secret(LOG_WARN, dh2, p1, DH_BYTES, s2, 50);
- test_assert(s1len > 0);
- test_eq(s1len, s2len);
- test_memeq(s1, s2, s1len);
+ tt_assert(s1len > 0);
+ tt_int_op(s1len,==, s2len);
+ tt_mem_op(s1,==, s2, s1len);
{
/* XXXX Now fabricate some bad values and make sure they get caught,
@@ -63,17 +69,18 @@ test_crypto_dh(void)
/** Run unit tests for our random number generation function and its wrappers.
*/
static void
-test_crypto_rng(void)
+test_crypto_rng(void *arg)
{
int i, j, allok;
char data1[100], data2[100];
double d;
/* Try out RNG. */
- test_assert(! crypto_seed_rng(0));
+ (void)arg;
+ tt_assert(! crypto_seed_rng(0));
crypto_rand(data1, 100);
crypto_rand(data2, 100);
- test_memneq(data1,data2,100);
+ tt_mem_op(data1,!=, data2,100);
allok = 1;
for (i = 0; i < 100; ++i) {
uint64_t big;
@@ -88,8 +95,8 @@ test_crypto_rng(void)
if (big >= 5)
allok = 0;
d = crypto_rand_double();
- test_assert(d >= 0);
- test_assert(d < 1.0);
+ tt_assert(d >= 0);
+ tt_assert(d < 1.0);
host = crypto_random_hostname(3,8,"www.",".onion");
if (strcmpstart(host,"www.") ||
strcmpend(host,".onion") ||
@@ -98,7 +105,7 @@ test_crypto_rng(void)
allok = 0;
tor_free(host);
}
- test_assert(allok);
+ tt_assert(allok);
done:
;
}
@@ -128,15 +135,15 @@ test_crypto_aes(void *arg)
memset(data2, 0, 1024);
memset(data3, 0, 1024);
env1 = crypto_cipher_new(NULL);
- test_neq_ptr(env1, 0);
+ tt_ptr_op(env1, !=, NULL);
env2 = crypto_cipher_new(crypto_cipher_get_key(env1));
- test_neq_ptr(env2, 0);
+ tt_ptr_op(env2, !=, NULL);
/* Try encrypting 512 chars. */
crypto_cipher_encrypt(env1, data2, data1, 512);
crypto_cipher_decrypt(env2, data3, data2, 512);
- test_memeq(data1, data3, 512);
- test_memneq(data1, data2, 512);
+ tt_mem_op(data1,==, data3, 512);
+ tt_mem_op(data1,!=, data2, 512);
/* Now encrypt 1 at a time, and get 1 at a time. */
for (j = 512; j < 560; ++j) {
@@ -145,7 +152,7 @@ test_crypto_aes(void *arg)
for (j = 512; j < 560; ++j) {
crypto_cipher_decrypt(env2, data3+j, data2+j, 1);
}
- test_memeq(data1, data3, 560);
+ tt_mem_op(data1,==, data3, 560);
/* Now encrypt 3 at a time, and get 5 at a time. */
for (j = 560; j < 1024-5; j += 3) {
crypto_cipher_encrypt(env1, data2+j, data1+j, 3);
@@ -153,7 +160,7 @@ test_crypto_aes(void *arg)
for (j = 560; j < 1024-5; j += 5) {
crypto_cipher_decrypt(env2, data3+j, data2+j, 5);
}
- test_memeq(data1, data3, 1024-5);
+ tt_mem_op(data1,==, data3, 1024-5);
/* Now make sure that when we encrypt with different chunk sizes, we get
the same results. */
crypto_cipher_free(env2);
@@ -161,7 +168,7 @@ test_crypto_aes(void *arg)
memset(data3, 0, 1024);
env2 = crypto_cipher_new(crypto_cipher_get_key(env1));
- test_neq_ptr(env2, NULL);
+ tt_ptr_op(env2, !=, NULL);
for (j = 0; j < 1024-16; j += 17) {
crypto_cipher_encrypt(env2, data3+j, data1+j, 17);
}
@@ -170,7 +177,7 @@ test_crypto_aes(void *arg)
printf("%d: %d\t%d\n", j, (int) data2[j], (int) data3[j]);
}
}
- test_memeq(data2, data3, 1024-16);
+ tt_mem_op(data2,==, data3, 1024-16);
crypto_cipher_free(env1);
env1 = NULL;
crypto_cipher_free(env2);
@@ -237,7 +244,7 @@ test_crypto_aes(void *arg)
"\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xff\xff");
crypto_cipher_crypt_inplace(env1, data2, 64);
- test_assert(tor_mem_is_zero(data2, 64));
+ tt_assert(tor_mem_is_zero(data2, 64));
done:
tor_free(mem_op_hex_tmp);
@@ -252,7 +259,7 @@ test_crypto_aes(void *arg)
/** Run unit tests for our SHA-1 functionality */
static void
-test_crypto_sha(void)
+test_crypto_sha(void *arg)
{
crypto_digest_t *d1 = NULL, *d2 = NULL;
int i;
@@ -263,6 +270,7 @@ test_crypto_sha(void)
char *mem_op_hex_tmp=NULL;
/* Test SHA-1 with a test vector from the specification. */
+ (void)arg;
i = crypto_digest(data, "abc", 3);
test_memeq_hex(data, "A9993E364706816ABA3E25717850C26C9CD0D89D");
tt_int_op(i, ==, 0);
@@ -277,13 +285,13 @@ test_crypto_sha(void)
/* Case empty (wikipedia) */
crypto_hmac_sha256(digest, "", 0, "", 0);
- test_streq(hex_str(digest, 32),
+ tt_str_op(hex_str(digest, 32),==,
"B613679A0814D9EC772F95D778C35FC5FF1697C493715653C6C712144292C5AD");
/* Case quick-brown (wikipedia) */
crypto_hmac_sha256(digest, "key", 3,
"The quick brown fox jumps over the lazy dog", 43);
- test_streq(hex_str(digest, 32),
+ tt_str_op(hex_str(digest, 32),==,
"F7BC83F430538424B13298E6AA6FB143EF4D59A14946175997479DBC2D1A3CD8");
/* "Test Case 1" from RFC 4231 */
@@ -344,43 +352,43 @@ test_crypto_sha(void)
/* Incremental digest code. */
d1 = crypto_digest_new();
- test_assert(d1);
+ tt_assert(d1);
crypto_digest_add_bytes(d1, "abcdef", 6);
d2 = crypto_digest_dup(d1);
- test_assert(d2);
+ tt_assert(d2);
crypto_digest_add_bytes(d2, "ghijkl", 6);
crypto_digest_get_digest(d2, d_out1, sizeof(d_out1));
crypto_digest(d_out2, "abcdefghijkl", 12);
- test_memeq(d_out1, d_out2, DIGEST_LEN);
+ tt_mem_op(d_out1,==, d_out2, DIGEST_LEN);
crypto_digest_assign(d2, d1);
crypto_digest_add_bytes(d2, "mno", 3);
crypto_digest_get_digest(d2, d_out1, sizeof(d_out1));
crypto_digest(d_out2, "abcdefmno", 9);
- test_memeq(d_out1, d_out2, DIGEST_LEN);
+ tt_mem_op(d_out1,==, d_out2, DIGEST_LEN);
crypto_digest_get_digest(d1, d_out1, sizeof(d_out1));
crypto_digest(d_out2, "abcdef", 6);
- test_memeq(d_out1, d_out2, DIGEST_LEN);
+ tt_mem_op(d_out1,==, d_out2, DIGEST_LEN);
crypto_digest_free(d1);
crypto_digest_free(d2);
/* Incremental digest code with sha256 */
d1 = crypto_digest256_new(DIGEST_SHA256);
- test_assert(d1);
+ tt_assert(d1);
crypto_digest_add_bytes(d1, "abcdef", 6);
d2 = crypto_digest_dup(d1);
- test_assert(d2);
+ tt_assert(d2);
crypto_digest_add_bytes(d2, "ghijkl", 6);
crypto_digest_get_digest(d2, d_out1, sizeof(d_out1));
crypto_digest256(d_out2, "abcdefghijkl", 12, DIGEST_SHA256);
- test_memeq(d_out1, d_out2, DIGEST_LEN);
+ tt_mem_op(d_out1,==, d_out2, DIGEST_LEN);
crypto_digest_assign(d2, d1);
crypto_digest_add_bytes(d2, "mno", 3);
crypto_digest_get_digest(d2, d_out1, sizeof(d_out1));
crypto_digest256(d_out2, "abcdefmno", 9, DIGEST_SHA256);
- test_memeq(d_out1, d_out2, DIGEST_LEN);
+ tt_mem_op(d_out1,==, d_out2, DIGEST_LEN);
crypto_digest_get_digest(d1, d_out1, sizeof(d_out1));
crypto_digest256(d_out2, "abcdef", 6, DIGEST_SHA256);
- test_memeq(d_out1, d_out2, DIGEST_LEN);
+ tt_mem_op(d_out1,==, d_out2, DIGEST_LEN);
done:
if (d1)
@@ -392,7 +400,7 @@ test_crypto_sha(void)
/** Run unit tests for our public key crypto functions */
static void
-test_crypto_pk(void)
+test_crypto_pk(void *arg)
{
crypto_pk_t *pk1 = NULL, *pk2 = NULL;
char *encoded = NULL;
@@ -401,74 +409,83 @@ test_crypto_pk(void)
int i, len;
/* Public-key ciphers */
+ (void)arg;
pk1 = pk_generate(0);
pk2 = crypto_pk_new();
- test_assert(pk1 && pk2);
- test_assert(! crypto_pk_write_public_key_to_string(pk1, &encoded, &size));
- test_assert(! crypto_pk_read_public_key_from_string(pk2, encoded, size));
- test_eq(0, crypto_pk_cmp_keys(pk1, pk2));
+ tt_assert(pk1 && pk2);
+ tt_assert(! crypto_pk_write_public_key_to_string(pk1, &encoded, &size));
+ tt_assert(! crypto_pk_read_public_key_from_string(pk2, encoded, size));
+ tt_int_op(0,==, crypto_pk_cmp_keys(pk1, pk2));
/* comparison between keys and NULL */
tt_int_op(crypto_pk_cmp_keys(NULL, pk1), <, 0);
tt_int_op(crypto_pk_cmp_keys(NULL, NULL), ==, 0);
tt_int_op(crypto_pk_cmp_keys(pk1, NULL), >, 0);
- test_eq(128, crypto_pk_keysize(pk1));
- test_eq(1024, crypto_pk_num_bits(pk1));
- test_eq(128, crypto_pk_keysize(pk2));
- test_eq(1024, crypto_pk_num_bits(pk2));
+ tt_int_op(128,==, crypto_pk_keysize(pk1));
+ tt_int_op(1024,==, crypto_pk_num_bits(pk1));
+ tt_int_op(128,==, crypto_pk_keysize(pk2));
+ tt_int_op(1024,==, crypto_pk_num_bits(pk2));
- test_eq(128, crypto_pk_public_encrypt(pk2, data1, sizeof(data1),
+ tt_int_op(128,==, crypto_pk_public_encrypt(pk2, data1, sizeof(data1),
"Hello whirled.", 15,
PK_PKCS1_OAEP_PADDING));
- test_eq(128, crypto_pk_public_encrypt(pk1, data2, sizeof(data1),
+ tt_int_op(128,==, crypto_pk_public_encrypt(pk1, data2, sizeof(data1),
"Hello whirled.", 15,
PK_PKCS1_OAEP_PADDING));
/* oaep padding should make encryption not match */
- test_memneq(data1, data2, 128);
- test_eq(15, crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data1, 128,
+ tt_mem_op(data1,!=, data2, 128);
+ tt_int_op(15,==,
+ crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data1, 128,
PK_PKCS1_OAEP_PADDING,1));
- test_streq(data3, "Hello whirled.");
+ tt_str_op(data3,==, "Hello whirled.");
memset(data3, 0, 1024);
- test_eq(15, crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data2, 128,
+ tt_int_op(15,==,
+ crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data2, 128,
PK_PKCS1_OAEP_PADDING,1));
- test_streq(data3, "Hello whirled.");
+ tt_str_op(data3,==, "Hello whirled.");
/* Can't decrypt with public key. */
- test_eq(-1, crypto_pk_private_decrypt(pk2, data3, sizeof(data3), data2, 128,
+ tt_int_op(-1,==,
+ crypto_pk_private_decrypt(pk2, data3, sizeof(data3), data2, 128,
PK_PKCS1_OAEP_PADDING,1));
/* Try again with bad padding */
memcpy(data2+1, "XYZZY", 5); /* This has fails ~ once-in-2^40 */
- test_eq(-1, crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data2, 128,
+ tt_int_op(-1,==,
+ crypto_pk_private_decrypt(pk1, data3, sizeof(data3), data2, 128,
PK_PKCS1_OAEP_PADDING,1));
/* File operations: save and load private key */
- test_assert(! crypto_pk_write_private_key_to_filename(pk1,
+ tt_assert(! crypto_pk_write_private_key_to_filename(pk1,
get_fname("pkey1")));
/* failing case for read: can't read. */
- test_assert(crypto_pk_read_private_key_from_filename(pk2,
+ tt_assert(crypto_pk_read_private_key_from_filename(pk2,
get_fname("xyzzy")) < 0);
write_str_to_file(get_fname("xyzzy"), "foobar", 6);
/* Failing case for read: no key. */
- test_assert(crypto_pk_read_private_key_from_filename(pk2,
+ tt_assert(crypto_pk_read_private_key_from_filename(pk2,
get_fname("xyzzy")) < 0);
- test_assert(! crypto_pk_read_private_key_from_filename(pk2,
+ tt_assert(! crypto_pk_read_private_key_from_filename(pk2,
get_fname("pkey1")));
- test_eq(15, crypto_pk_private_decrypt(pk2, data3, sizeof(data3), data1, 128,
+ tt_int_op(15,==,
+ crypto_pk_private_decrypt(pk2, data3, sizeof(data3), data1, 128,
PK_PKCS1_OAEP_PADDING,1));
/* Now try signing. */
strlcpy(data1, "Ossifrage", 1024);
- test_eq(128, crypto_pk_private_sign(pk1, data2, sizeof(data2), data1, 10));
- test_eq(10,
+ tt_int_op(128,==,
+ crypto_pk_private_sign(pk1, data2, sizeof(data2), data1, 10));
+ tt_int_op(10,==,
crypto_pk_public_checksig(pk1, data3, sizeof(data3), data2, 128));
- test_streq(data3, "Ossifrage");
+ tt_str_op(data3,==, "Ossifrage");
/* Try signing digests. */
- test_eq(128, crypto_pk_private_sign_digest(pk1, data2, sizeof(data2),
+ tt_int_op(128,==, crypto_pk_private_sign_digest(pk1, data2, sizeof(data2),
data1, 10));
- test_eq(20,
+ tt_int_op(20,==,
crypto_pk_public_checksig(pk1, data3, sizeof(data3), data2, 128));
- test_eq(0, crypto_pk_public_checksig_digest(pk1, data1, 10, data2, 128));
- test_eq(-1, crypto_pk_public_checksig_digest(pk1, data1, 11, data2, 128));
+ tt_int_op(0,==,
+ crypto_pk_public_checksig_digest(pk1, data1, 10, data2, 128));
+ tt_int_op(-1,==,
+ crypto_pk_public_checksig_digest(pk1, data1, 11, data2, 128));
/*XXXX test failed signing*/
@@ -476,9 +493,9 @@ test_crypto_pk(void)
crypto_pk_free(pk2);
pk2 = NULL;
i = crypto_pk_asn1_encode(pk1, data1, 1024);
- test_assert(i>0);
+ tt_int_op(i, >, 0);
pk2 = crypto_pk_asn1_decode(data1, i);
- test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0);
+ tt_assert(crypto_pk_cmp_keys(pk1,pk2) == 0);
/* Try with hybrid encryption wrappers. */
crypto_rand(data1, 1024);
@@ -487,19 +504,19 @@ test_crypto_pk(void)
memset(data3,0,1024);
len = crypto_pk_public_hybrid_encrypt(pk1,data2,sizeof(data2),
data1,i,PK_PKCS1_OAEP_PADDING,0);
- test_assert(len>=0);
+ tt_int_op(len, >=, 0);
len = crypto_pk_private_hybrid_decrypt(pk1,data3,sizeof(data3),
data2,len,PK_PKCS1_OAEP_PADDING,1);
- test_eq(len,i);
- test_memeq(data1,data3,i);
+ tt_int_op(len,==, i);
+ tt_mem_op(data1,==, data3,i);
}
/* Try copy_full */
crypto_pk_free(pk2);
pk2 = crypto_pk_copy_full(pk1);
- test_assert(pk2 != NULL);
- test_neq_ptr(pk1, pk2);
- test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0);
+ tt_assert(pk2 != NULL);
+ tt_ptr_op(pk1, !=, pk2);
+ tt_assert(crypto_pk_cmp_keys(pk1,pk2) == 0);
done:
if (pk1)
@@ -532,7 +549,7 @@ test_crypto_pk_fingerprints(void *arg)
/* Is digest as expected? */
crypto_digest(d, encoded, n);
tt_int_op(0, ==, crypto_pk_get_digest(pk, d2));
- test_memeq(d, d2, DIGEST_LEN);
+ tt_mem_op(d,==, d2, DIGEST_LEN);
/* Is fingerprint right? */
tt_int_op(0, ==, crypto_pk_get_fingerprint(pk, fingerprint, 0));
@@ -561,28 +578,29 @@ test_crypto_pk_fingerprints(void *arg)
/** Sanity check for crypto pk digests */
static void
-test_crypto_digests(void)
+test_crypto_digests(void *arg)
{
crypto_pk_t *k = NULL;
ssize_t r;
digests_t pkey_digests;
char digest[DIGEST_LEN];
+ (void)arg;
k = crypto_pk_new();
- test_assert(k);
+ tt_assert(k);
r = crypto_pk_read_private_key_from_string(k, AUTHORITY_SIGNKEY_3, -1);
- test_assert(!r);
+ tt_assert(!r);
r = crypto_pk_get_digest(k, digest);
- test_assert(r == 0);
- test_memeq(hex_str(digest, DIGEST_LEN),
+ tt_assert(r == 0);
+ tt_mem_op(hex_str(digest, DIGEST_LEN),==,
AUTHORITY_SIGNKEY_A_DIGEST, HEX_DIGEST_LEN);
r = crypto_pk_get_all_digests(k, &pkey_digests);
- test_memeq(hex_str(pkey_digests.d[DIGEST_SHA1], DIGEST_LEN),
+ tt_mem_op(hex_str(pkey_digests.d[DIGEST_SHA1], DIGEST_LEN),==,
AUTHORITY_SIGNKEY_A_DIGEST, HEX_DIGEST_LEN);
- test_memeq(hex_str(pkey_digests.d[DIGEST_SHA256], DIGEST256_LEN),
+ tt_mem_op(hex_str(pkey_digests.d[DIGEST_SHA256], DIGEST256_LEN),==,
AUTHORITY_SIGNKEY_A_DIGEST256, HEX_DIGEST256_LEN);
done:
crypto_pk_free(k);
@@ -591,58 +609,59 @@ test_crypto_digests(void)
/** Run unit tests for misc crypto formatting functionality (base64, base32,
* fingerprints, etc) */
static void
-test_crypto_formats(void)
+test_crypto_formats(void *arg)
{
char *data1 = NULL, *data2 = NULL, *data3 = NULL;
int i, j, idx;
+ (void)arg;
data1 = tor_malloc(1024);
data2 = tor_malloc(1024);
data3 = tor_malloc(1024);
- test_assert(data1 && data2 && data3);
+ tt_assert(data1 && data2 && data3);
/* Base64 tests */
memset(data1, 6, 1024);
for (idx = 0; idx < 10; ++idx) {
i = base64_encode(data2, 1024, data1, idx);
- test_assert(i >= 0);
+ tt_int_op(i, >=, 0);
j = base64_decode(data3, 1024, data2, i);
- test_eq(j,idx);
- test_memeq(data3, data1, idx);
+ tt_int_op(j,==, idx);
+ tt_mem_op(data3,==, data1, idx);
}
strlcpy(data1, "Test string that contains 35 chars.", 1024);
strlcat(data1, " 2nd string that contains 35 chars.", 1024);
i = base64_encode(data2, 1024, data1, 71);
- test_assert(i >= 0);
+ tt_int_op(i, >=, 0);
j = base64_decode(data3, 1024, data2, i);
- test_eq(j, 71);
- test_streq(data3, data1);
- test_assert(data2[i] == '\0');
+ tt_int_op(j,==, 71);
+ tt_str_op(data3,==, data1);
+ tt_int_op(data2[i], ==, '\0');
crypto_rand(data1, DIGEST_LEN);
memset(data2, 100, 1024);
digest_to_base64(data2, data1);
- test_eq(BASE64_DIGEST_LEN, strlen(data2));
- test_eq(100, data2[BASE64_DIGEST_LEN+2]);
+ tt_int_op(BASE64_DIGEST_LEN,==, strlen(data2));
+ tt_int_op(100,==, data2[BASE64_DIGEST_LEN+2]);
memset(data3, 99, 1024);
- test_eq(digest_from_base64(data3, data2), 0);
- test_memeq(data1, data3, DIGEST_LEN);
- test_eq(99, data3[DIGEST_LEN+1]);
+ tt_int_op(digest_from_base64(data3, data2),==, 0);
+ tt_mem_op(data1,==, data3, DIGEST_LEN);
+ tt_int_op(99,==, data3[DIGEST_LEN+1]);
- test_assert(digest_from_base64(data3, "###") < 0);
+ tt_assert(digest_from_base64(data3, "###") < 0);
/* Encoding SHA256 */
crypto_rand(data2, DIGEST256_LEN);
memset(data2, 100, 1024);
digest256_to_base64(data2, data1);
- test_eq(BASE64_DIGEST256_LEN, strlen(data2));
- test_eq(100, data2[BASE64_DIGEST256_LEN+2]);
+ tt_int_op(BASE64_DIGEST256_LEN,==, strlen(data2));
+ tt_int_op(100,==, data2[BASE64_DIGEST256_LEN+2]);
memset(data3, 99, 1024);
- test_eq(digest256_from_base64(data3, data2), 0);
- test_memeq(data1, data3, DIGEST256_LEN);
- test_eq(99, data3[DIGEST256_LEN+1]);
+ tt_int_op(digest256_from_base64(data3, data2),==, 0);
+ tt_mem_op(data1,==, data3, DIGEST256_LEN);
+ tt_int_op(99,==, data3[DIGEST256_LEN+1]);
/* Base32 tests */
strlcpy(data1, "5chrs", 1024);
@@ -651,27 +670,27 @@ test_crypto_formats(void)
* By 5s: [00110 10101 10001 10110 10000 11100 10011 10011]
*/
base32_encode(data2, 9, data1, 5);
- test_streq(data2, "gvrwq4tt");
+ tt_str_op(data2,==, "gvrwq4tt");
strlcpy(data1, "\xFF\xF5\x6D\x44\xAE\x0D\x5C\xC9\x62\xC4", 1024);
base32_encode(data2, 30, data1, 10);
- test_streq(data2, "772w2rfobvomsywe");
+ tt_str_op(data2,==, "772w2rfobvomsywe");
/* Base16 tests */
strlcpy(data1, "6chrs\xff", 1024);
base16_encode(data2, 13, data1, 6);
- test_streq(data2, "3663687273FF");
+ tt_str_op(data2,==, "3663687273FF");
strlcpy(data1, "f0d678affc000100", 1024);
i = base16_decode(data2, 8, data1, 16);
- test_eq(i,0);
- test_memeq(data2, "\xf0\xd6\x78\xaf\xfc\x00\x01\x00",8);
+ tt_int_op(i,==, 0);
+ tt_mem_op(data2,==, "\xf0\xd6\x78\xaf\xfc\x00\x01\x00",8);
/* now try some failing base16 decodes */
- test_eq(-1, base16_decode(data2, 8, data1, 15)); /* odd input len */
- test_eq(-1, base16_decode(data2, 7, data1, 16)); /* dest too short */
+ tt_int_op(-1,==, base16_decode(data2, 8, data1, 15)); /* odd input len */
+ tt_int_op(-1,==, base16_decode(data2, 7, data1, 16)); /* dest too short */
strlcpy(data1, "f0dz!8affc000100", 1024);
- test_eq(-1, base16_decode(data2, 8, data1, 16));
+ tt_int_op(-1,==, base16_decode(data2, 8, data1, 16));
tor_free(data1);
tor_free(data2);
@@ -680,10 +699,10 @@ test_crypto_formats(void)
/* Add spaces to fingerprint */
{
data1 = tor_strdup("ABCD1234ABCD56780000ABCD1234ABCD56780000");
- test_eq(strlen(data1), 40);
+ tt_int_op(strlen(data1),==, 40);
data2 = tor_malloc(FINGERPRINT_LEN+1);
crypto_add_spaces_to_fp(data2, FINGERPRINT_LEN+1, data1);
- test_streq(data2, "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 0000");
+ tt_str_op(data2,==, "ABCD 1234 ABCD 5678 0000 ABCD 1234 ABCD 5678 0000");
tor_free(data1);
tor_free(data2);
}
@@ -696,37 +715,377 @@ test_crypto_formats(void)
/** Run unit tests for our secret-to-key passphrase hashing functionality. */
static void
-test_crypto_s2k(void)
+test_crypto_s2k_rfc2440(void *arg)
{
char buf[29];
char buf2[29];
char *buf3 = NULL;
int i;
+ (void)arg;
memset(buf, 0, sizeof(buf));
memset(buf2, 0, sizeof(buf2));
buf3 = tor_malloc(65536);
memset(buf3, 0, 65536);
- secret_to_key(buf+9, 20, "", 0, buf);
+ secret_to_key_rfc2440(buf+9, 20, "", 0, buf);
crypto_digest(buf2+9, buf3, 1024);
- test_memeq(buf, buf2, 29);
+ tt_mem_op(buf,==, buf2, 29);
memcpy(buf,"vrbacrda",8);
memcpy(buf2,"vrbacrda",8);
buf[8] = 96;
buf2[8] = 96;
- secret_to_key(buf+9, 20, "12345678", 8, buf);
+ secret_to_key_rfc2440(buf+9, 20, "12345678", 8, buf);
for (i = 0; i < 65536; i += 16) {
memcpy(buf3+i, "vrbacrda12345678", 16);
}
crypto_digest(buf2+9, buf3, 65536);
- test_memeq(buf, buf2, 29);
+ tt_mem_op(buf,==, buf2, 29);
done:
tor_free(buf3);
}
+static void
+run_s2k_tests(const unsigned flags, const unsigned type,
+ int speclen, const int keylen, int legacy)
+{
+ uint8_t buf[S2K_MAXLEN], buf2[S2K_MAXLEN], buf3[S2K_MAXLEN];
+ int r;
+ size_t sz;
+ const char pw1[] = "You can't come in here unless you say swordfish!";
+ const char pw2[] = "Now, I give you one more guess.";
+
+ r = secret_to_key_new(buf, sizeof(buf), &sz,
+ pw1, strlen(pw1), flags);
+ tt_int_op(r, ==, S2K_OKAY);
+ tt_int_op(buf[0], ==, type);
+
+ tt_int_op(sz, ==, keylen + speclen);
+
+ if (legacy) {
+ memmove(buf, buf+1, sz-1);
+ --sz;
+ --speclen;
+ }
+
+ tt_int_op(S2K_OKAY, ==,
+ secret_to_key_check(buf, sz, pw1, strlen(pw1)));
+
+ tt_int_op(S2K_BAD_SECRET, ==,
+ secret_to_key_check(buf, sz, pw2, strlen(pw2)));
+
+ /* Move key to buf2, and clear it. */
+ memset(buf3, 0, sizeof(buf3));
+ memcpy(buf2, buf+speclen, keylen);
+ memset(buf+speclen, 0, sz - speclen);
+
+ /* Derivekey should produce the same results. */
+ tt_int_op(S2K_OKAY, ==,
+ secret_to_key_derivekey(buf3, keylen, buf, speclen, pw1, strlen(pw1)));
+
+ tt_mem_op(buf2, ==, buf3, keylen);
+
+ /* Derivekey with a longer output should fill the output. */
+ memset(buf2, 0, sizeof(buf2));
+ tt_int_op(S2K_OKAY, ==,
+ secret_to_key_derivekey(buf2, sizeof(buf2), buf, speclen,
+ pw1, strlen(pw1)));
+
+ tt_mem_op(buf2, !=, buf3, sizeof(buf2));
+
+ memset(buf3, 0, sizeof(buf3));
+ tt_int_op(S2K_OKAY, ==,
+ secret_to_key_derivekey(buf3, sizeof(buf3), buf, speclen,
+ pw1, strlen(pw1)));
+ tt_mem_op(buf2, ==, buf3, sizeof(buf3));
+ tt_assert(!tor_mem_is_zero((char*)buf2+keylen, sizeof(buf2)-keylen));
+
+ done:
+ ;
+}
+
+static void
+test_crypto_s2k_general(void *arg)
+{
+ const char *which = arg;
+
+ if (!strcmp(which, "scrypt")) {
+ run_s2k_tests(0, 2, 19, 32, 0);
+ } else if (!strcmp(which, "scrypt-low")) {
+ run_s2k_tests(S2K_FLAG_LOW_MEM, 2, 19, 32, 0);
+ } else if (!strcmp(which, "pbkdf2")) {
+ run_s2k_tests(S2K_FLAG_USE_PBKDF2, 1, 18, 20, 0);
+ } else if (!strcmp(which, "rfc2440")) {
+ run_s2k_tests(S2K_FLAG_NO_SCRYPT, 0, 10, 20, 0);
+ } else if (!strcmp(which, "rfc2440-legacy")) {
+ run_s2k_tests(S2K_FLAG_NO_SCRYPT, 0, 10, 20, 1);
+ } else {
+ tt_fail();
+ }
+}
+
+static void
+test_crypto_s2k_errors(void *arg)
+{
+ uint8_t buf[S2K_MAXLEN], buf2[S2K_MAXLEN];
+ size_t sz;
+
+ (void)arg;
+
+ /* Bogus specifiers: simple */
+ tt_int_op(S2K_BAD_LEN, ==,
+ secret_to_key_derivekey(buf, sizeof(buf),
+ (const uint8_t*)"", 0, "ABC", 3));
+ tt_int_op(S2K_BAD_ALGORITHM, ==,
+ secret_to_key_derivekey(buf, sizeof(buf),
+ (const uint8_t*)"\x10", 1, "ABC", 3));
+ tt_int_op(S2K_BAD_LEN, ==,
+ secret_to_key_derivekey(buf, sizeof(buf),
+ (const uint8_t*)"\x01\x02", 2, "ABC", 3));
+
+ tt_int_op(S2K_BAD_LEN, ==,
+ secret_to_key_check((const uint8_t*)"", 0, "ABC", 3));
+ tt_int_op(S2K_BAD_ALGORITHM, ==,
+ secret_to_key_check((const uint8_t*)"\x10", 1, "ABC", 3));
+ tt_int_op(S2K_BAD_LEN, ==,
+ secret_to_key_check((const uint8_t*)"\x01\x02", 2, "ABC", 3));
+
+ /* too long gets "BAD_LEN" too */
+ memset(buf, 0, sizeof(buf));
+ buf[0] = 2;
+ tt_int_op(S2K_BAD_LEN, ==,
+ secret_to_key_derivekey(buf2, sizeof(buf2),
+ buf, sizeof(buf), "ABC", 3));
+
+ /* Truncated output */
+#ifdef HAVE_LIBSCRYPT_H
+ tt_int_op(S2K_TRUNCATED, ==, secret_to_key_new(buf, 50, &sz,
+ "ABC", 3, 0));
+ tt_int_op(S2K_TRUNCATED, ==, secret_to_key_new(buf, 50, &sz,
+ "ABC", 3, S2K_FLAG_LOW_MEM));
+#endif
+ tt_int_op(S2K_TRUNCATED, ==, secret_to_key_new(buf, 37, &sz,
+ "ABC", 3, S2K_FLAG_USE_PBKDF2));
+ tt_int_op(S2K_TRUNCATED, ==, secret_to_key_new(buf, 29, &sz,
+ "ABC", 3, S2K_FLAG_NO_SCRYPT));
+
+#ifdef HAVE_LIBSCRYPT_H
+ tt_int_op(S2K_TRUNCATED, ==, secret_to_key_make_specifier(buf, 18, 0));
+ tt_int_op(S2K_TRUNCATED, ==, secret_to_key_make_specifier(buf, 18,
+ S2K_FLAG_LOW_MEM));
+#endif
+ tt_int_op(S2K_TRUNCATED, ==, secret_to_key_make_specifier(buf, 17,
+ S2K_FLAG_USE_PBKDF2));
+ tt_int_op(S2K_TRUNCATED, ==, secret_to_key_make_specifier(buf, 9,
+ S2K_FLAG_NO_SCRYPT));
+
+ /* Now try using type-specific bogus specifiers. */
+
+ /* It's a bad pbkdf2 buffer if it has an iteration count that would overflow
+ * int32_t. */
+ memset(buf, 0, sizeof(buf));
+ buf[0] = 1; /* pbkdf2 */
+ buf[17] = 100; /* 1<<100 is much bigger than INT32_MAX */
+ tt_int_op(S2K_BAD_PARAMS, ==,
+ secret_to_key_derivekey(buf2, sizeof(buf2),
+ buf, 18, "ABC", 3));
+
+#ifdef HAVE_LIBSCRYPT_H
+ /* It's a bad scrypt buffer if N would overflow uint64 */
+ memset(buf, 0, sizeof(buf));
+ buf[0] = 2; /* scrypt */
+ buf[17] = 100; /* 1<<100 is much bigger than UINT64_MAX */
+ tt_int_op(S2K_BAD_PARAMS, ==,
+ secret_to_key_derivekey(buf2, sizeof(buf2),
+ buf, 19, "ABC", 3));
+#endif
+
+ done:
+ ;
+}
+
+static void
+test_crypto_scrypt_vectors(void *arg)
+{
+ char *mem_op_hex_tmp = NULL;
+ uint8_t spec[64], out[64];
+
+ (void)arg;
+#ifndef HAVE_LIBSCRYPT_H
+ if (1)
+ tt_skip();
+#endif
+
+ /* Test vectors from
+ http://tools.ietf.org/html/draft-josefsson-scrypt-kdf-00 section 11.
+
+ Note that the names of 'r' and 'N' are switched in that section. Or
+ possibly in libscrypt.
+ */
+
+ base16_decode((char*)spec, sizeof(spec),
+ "0400", 4);
+ memset(out, 0x00, sizeof(out));
+ tt_int_op(64, ==,
+ secret_to_key_compute_key(out, 64, spec, 2, "", 0, 2));
+ test_memeq_hex(out,
+ "77d6576238657b203b19ca42c18a0497"
+ "f16b4844e3074ae8dfdffa3fede21442"
+ "fcd0069ded0948f8326a753a0fc81f17"
+ "e8d3e0fb2e0d3628cf35e20c38d18906");
+
+ base16_decode((char*)spec, sizeof(spec),
+ "4e61436c" "0A34", 12);
+ memset(out, 0x00, sizeof(out));
+ tt_int_op(64, ==,
+ secret_to_key_compute_key(out, 64, spec, 6, "password", 8, 2));
+ test_memeq_hex(out,
+ "fdbabe1c9d3472007856e7190d01e9fe"
+ "7c6ad7cbc8237830e77376634b373162"
+ "2eaf30d92e22a3886ff109279d9830da"
+ "c727afb94a83ee6d8360cbdfa2cc0640");
+
+ base16_decode((char*)spec, sizeof(spec),
+ "536f6469756d43686c6f72696465" "0e30", 32);
+ memset(out, 0x00, sizeof(out));
+ tt_int_op(64, ==,
+ secret_to_key_compute_key(out, 64, spec, 16,
+ "pleaseletmein", 13, 2));
+ test_memeq_hex(out,
+ "7023bdcb3afd7348461c06cd81fd38eb"
+ "fda8fbba904f8e3ea9b543f6545da1f2"
+ "d5432955613f0fcf62d49705242a9af9"
+ "e61e85dc0d651e40dfcf017b45575887");
+
+ base16_decode((char*)spec, sizeof(spec),
+ "536f6469756d43686c6f72696465" "1430", 32);
+ memset(out, 0x00, sizeof(out));
+ tt_int_op(64, ==,
+ secret_to_key_compute_key(out, 64, spec, 16,
+ "pleaseletmein", 13, 2));
+ test_memeq_hex(out,
+ "2101cb9b6a511aaeaddbbe09cf70f881"
+ "ec568d574a2ffd4dabe5ee9820adaa47"
+ "8e56fd8f4ba5d09ffa1c6d927c40f4c3"
+ "37304049e8a952fbcbf45c6fa77a41a4");
+
+ done:
+ tor_free(mem_op_hex_tmp);
+}
+
+static void
+test_crypto_pbkdf2_vectors(void *arg)
+{
+ char *mem_op_hex_tmp = NULL;
+ uint8_t spec[64], out[64];
+ (void)arg;
+
+ /* Test vectors from RFC6070, section 2 */
+ base16_decode((char*)spec, sizeof(spec),
+ "73616c74" "00" , 10);
+ memset(out, 0x00, sizeof(out));
+ tt_int_op(20, ==,
+ secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
+ test_memeq_hex(out, "0c60c80f961f0e71f3a9b524af6012062fe037a6");
+
+ base16_decode((char*)spec, sizeof(spec),
+ "73616c74" "01" , 10);
+ memset(out, 0x00, sizeof(out));
+ tt_int_op(20, ==,
+ secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
+ test_memeq_hex(out, "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957");
+
+ base16_decode((char*)spec, sizeof(spec),
+ "73616c74" "0C" , 10);
+ memset(out, 0x00, sizeof(out));
+ tt_int_op(20, ==,
+ secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
+ test_memeq_hex(out, "4b007901b765489abead49d926f721d065a429c1");
+
+ base16_decode((char*)spec, sizeof(spec),
+ "73616c74" "18" , 10);
+ memset(out, 0x00, sizeof(out));
+ tt_int_op(20, ==,
+ secret_to_key_compute_key(out, 20, spec, 5, "password", 8, 1));
+ test_memeq_hex(out, "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984");
+
+ base16_decode((char*)spec, sizeof(spec),
+ "73616c7453414c5473616c7453414c5473616c745"
+ "3414c5473616c7453414c5473616c74" "0C" , 74);
+ memset(out, 0x00, sizeof(out));
+ tt_int_op(25, ==,
+ secret_to_key_compute_key(out, 25, spec, 37,
+ "passwordPASSWORDpassword", 24, 1));
+ test_memeq_hex(out, "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038");
+
+ base16_decode((char*)spec, sizeof(spec),
+ "7361006c74" "0c" , 12);
+ memset(out, 0x00, sizeof(out));
+ tt_int_op(16, ==,
+ secret_to_key_compute_key(out, 16, spec, 6, "pass\0word", 9, 1));
+ test_memeq_hex(out, "56fa6aa75548099dcc37d7f03425e0c3");
+
+ done:
+ tor_free(mem_op_hex_tmp);
+}
+
+static void
+test_crypto_pwbox(void *arg)
+{
+ uint8_t *boxed=NULL, *decoded=NULL;
+ size_t len, dlen;
+ unsigned i;
+ const char msg[] = "This bunny reminds you that you still have a "
+ "salamander in your sylladex. She is holding the bunny Dave got you. "
+ "It’s sort of uncanny how similar they are, aside from the knitted "
+ "enhancements. Seriously, what are the odds?? So weird.";
+ const char pw[] = "I'm a night owl and a wise bird too";
+
+ const unsigned flags[] = { 0,
+ S2K_FLAG_NO_SCRYPT,
+ S2K_FLAG_LOW_MEM,
+ S2K_FLAG_NO_SCRYPT|S2K_FLAG_LOW_MEM,
+ S2K_FLAG_USE_PBKDF2 };
+ (void)arg;
+
+ for (i = 0; i < ARRAY_LENGTH(flags); ++i) {
+ tt_int_op(0, ==, crypto_pwbox(&boxed, &len,
+ (const uint8_t*)msg, strlen(msg),
+ pw, strlen(pw), flags[i]));
+ tt_assert(boxed);
+ tt_assert(len > 128+32);
+
+ tt_int_op(0, ==, crypto_unpwbox(&decoded, &dlen, boxed, len,
+ pw, strlen(pw)));
+
+ tt_assert(decoded);
+ tt_uint_op(dlen, ==, strlen(msg));
+ tt_mem_op(decoded, ==, msg, dlen);
+
+ tor_free(decoded);
+
+ tt_int_op(UNPWBOX_BAD_SECRET, ==, crypto_unpwbox(&decoded, &dlen,
+ boxed, len,
+ pw, strlen(pw)-1));
+ boxed[len-1] ^= 1;
+ tt_int_op(UNPWBOX_BAD_SECRET, ==, crypto_unpwbox(&decoded, &dlen,
+ boxed, len,
+ pw, strlen(pw)));
+ boxed[0] = 255;
+ tt_int_op(UNPWBOX_CORRUPTED, ==, crypto_unpwbox(&decoded, &dlen,
+ boxed, len,
+ pw, strlen(pw)));
+
+ tor_free(boxed);
+ }
+
+ done:
+ tor_free(boxed);
+ tor_free(decoded);
+}
+
/** Test AES-CTR encryption and decryption with IV. */
static void
test_crypto_aes_iv(void *arg)
@@ -757,79 +1116,79 @@ test_crypto_aes_iv(void *arg)
encrypted_size = crypto_cipher_encrypt_with_iv(key1, encrypted1, 16 + 4095,
plain, 4095);
- test_eq(encrypted_size, 16 + 4095);
+ tt_int_op(encrypted_size,==, 16 + 4095);
tt_assert(encrypted_size > 0); /* This is obviously true, since 4111 is
* greater than 0, but its truth is not
* obvious to all analysis tools. */
decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 4095,
encrypted1, encrypted_size);
- test_eq(decrypted_size, 4095);
+ tt_int_op(decrypted_size,==, 4095);
tt_assert(decrypted_size > 0);
- test_memeq(plain, decrypted1, 4095);
+ tt_mem_op(plain,==, decrypted1, 4095);
/* Encrypt a second time (with a new random initialization vector). */
encrypted_size = crypto_cipher_encrypt_with_iv(key1, encrypted2, 16 + 4095,
plain, 4095);
- test_eq(encrypted_size, 16 + 4095);
+ tt_int_op(encrypted_size,==, 16 + 4095);
tt_assert(encrypted_size > 0);
decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted2, 4095,
encrypted2, encrypted_size);
- test_eq(decrypted_size, 4095);
+ tt_int_op(decrypted_size,==, 4095);
tt_assert(decrypted_size > 0);
- test_memeq(plain, decrypted2, 4095);
- test_memneq(encrypted1, encrypted2, encrypted_size);
+ tt_mem_op(plain,==, decrypted2, 4095);
+ tt_mem_op(encrypted1,!=, encrypted2, encrypted_size);
/* Decrypt with the wrong key. */
decrypted_size = crypto_cipher_decrypt_with_iv(key2, decrypted2, 4095,
encrypted1, encrypted_size);
- test_eq(decrypted_size, 4095);
- test_memneq(plain, decrypted2, decrypted_size);
+ tt_int_op(decrypted_size,==, 4095);
+ tt_mem_op(plain,!=, decrypted2, decrypted_size);
/* Alter the initialization vector. */
encrypted1[0] += 42;
decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 4095,
encrypted1, encrypted_size);
- test_eq(decrypted_size, 4095);
- test_memneq(plain, decrypted2, 4095);
+ tt_int_op(decrypted_size,==, 4095);
+ tt_mem_op(plain,!=, decrypted2, 4095);
/* Special length case: 1. */
encrypted_size = crypto_cipher_encrypt_with_iv(key1, encrypted1, 16 + 1,
plain_1, 1);
- test_eq(encrypted_size, 16 + 1);
+ tt_int_op(encrypted_size,==, 16 + 1);
tt_assert(encrypted_size > 0);
decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 1,
encrypted1, encrypted_size);
- test_eq(decrypted_size, 1);
+ tt_int_op(decrypted_size,==, 1);
tt_assert(decrypted_size > 0);
- test_memeq(plain_1, decrypted1, 1);
+ tt_mem_op(plain_1,==, decrypted1, 1);
/* Special length case: 15. */
encrypted_size = crypto_cipher_encrypt_with_iv(key1, encrypted1, 16 + 15,
plain_15, 15);
- test_eq(encrypted_size, 16 + 15);
+ tt_int_op(encrypted_size,==, 16 + 15);
tt_assert(encrypted_size > 0);
decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 15,
encrypted1, encrypted_size);
- test_eq(decrypted_size, 15);
+ tt_int_op(decrypted_size,==, 15);
tt_assert(decrypted_size > 0);
- test_memeq(plain_15, decrypted1, 15);
+ tt_mem_op(plain_15,==, decrypted1, 15);
/* Special length case: 16. */
encrypted_size = crypto_cipher_encrypt_with_iv(key1, encrypted1, 16 + 16,
plain_16, 16);
- test_eq(encrypted_size, 16 + 16);
+ tt_int_op(encrypted_size,==, 16 + 16);
tt_assert(encrypted_size > 0);
decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 16,
encrypted1, encrypted_size);
- test_eq(decrypted_size, 16);
+ tt_int_op(decrypted_size,==, 16);
tt_assert(decrypted_size > 0);
- test_memeq(plain_16, decrypted1, 16);
+ tt_mem_op(plain_16,==, decrypted1, 16);
/* Special length case: 17. */
encrypted_size = crypto_cipher_encrypt_with_iv(key1, encrypted1, 16 + 17,
plain_17, 17);
- test_eq(encrypted_size, 16 + 17);
+ tt_int_op(encrypted_size,==, 16 + 17);
tt_assert(encrypted_size > 0);
decrypted_size = crypto_cipher_decrypt_with_iv(key1, decrypted1, 17,
encrypted1, encrypted_size);
- test_eq(decrypted_size, 17);
+ tt_int_op(decrypted_size,==, 17);
tt_assert(decrypted_size > 0);
- test_memeq(plain_17, decrypted1, 17);
+ tt_mem_op(plain_17,==, decrypted1, 17);
done:
/* Free memory. */
@@ -842,34 +1201,35 @@ test_crypto_aes_iv(void *arg)
/** Test base32 decoding. */
static void
-test_crypto_base32_decode(void)
+test_crypto_base32_decode(void *arg)
{
char plain[60], encoded[96 + 1], decoded[60];
int res;
+ (void)arg;
crypto_rand(plain, 60);
/* Encode and decode a random string. */
base32_encode(encoded, 96 + 1, plain, 60);
res = base32_decode(decoded, 60, encoded, 96);
- test_eq(res, 0);
- test_memeq(plain, decoded, 60);
+ tt_int_op(res,==, 0);
+ tt_mem_op(plain,==, decoded, 60);
/* Encode, uppercase, and decode a random string. */
base32_encode(encoded, 96 + 1, plain, 60);
tor_strupper(encoded);
res = base32_decode(decoded, 60, encoded, 96);
- test_eq(res, 0);
- test_memeq(plain, decoded, 60);
+ tt_int_op(res,==, 0);
+ tt_mem_op(plain,==, decoded, 60);
/* Change encoded string and decode. */
if (encoded[0] == 'A' || encoded[0] == 'a')
encoded[0] = 'B';
else
encoded[0] = 'A';
res = base32_decode(decoded, 60, encoded, 96);
- test_eq(res, 0);
- test_memneq(plain, decoded, 60);
+ tt_int_op(res,==, 0);
+ tt_mem_op(plain,!=, decoded, 60);
/* Bad encodings. */
encoded[0] = '!';
res = base32_decode(decoded, 60, encoded, 96);
- test_assert(res < 0);
+ tt_int_op(0, >, res);
done:
;
@@ -1024,7 +1384,7 @@ test_crypto_curve25519_impl(void *arg)
e2k[31] |= (byte & 0x80);
}
curve25519_impl(e1e2k,e1,e2k);
- test_memeq(e1e2k, e2e1k, 32);
+ tt_mem_op(e1e2k,==, e2e1k, 32);
if (loop == loop_max-1) {
break;
}
@@ -1056,11 +1416,11 @@ test_crypto_curve25519_wrappers(void *arg)
curve25519_secret_key_generate(&seckey2, 1);
curve25519_public_key_generate(&pubkey1, &seckey1);
curve25519_public_key_generate(&pubkey2, &seckey2);
- test_assert(curve25519_public_key_is_ok(&pubkey1));
- test_assert(curve25519_public_key_is_ok(&pubkey2));
+ tt_assert(curve25519_public_key_is_ok(&pubkey1));
+ tt_assert(curve25519_public_key_is_ok(&pubkey2));
curve25519_handshake(output1, &seckey1, &pubkey2);
curve25519_handshake(output2, &seckey2, &pubkey1);
- test_memeq(output1, output2, sizeof(output1));
+ tt_mem_op(output1,==, output2, sizeof(output1));
done:
;
@@ -1081,12 +1441,12 @@ test_crypto_curve25519_encode(void *arg)
tt_int_op(CURVE25519_BASE64_PADDED_LEN, ==, strlen(buf));
tt_int_op(0, ==, curve25519_public_from_base64(&key2, buf));
- test_memeq(key1.public_key, key2.public_key, CURVE25519_PUBKEY_LEN);
+ tt_mem_op(key1.public_key,==, key2.public_key, CURVE25519_PUBKEY_LEN);
buf[CURVE25519_BASE64_PADDED_LEN - 1] = '\0';
tt_int_op(CURVE25519_BASE64_PADDED_LEN-1, ==, strlen(buf));
tt_int_op(0, ==, curve25519_public_from_base64(&key3, buf));
- test_memeq(key1.public_key, key3.public_key, CURVE25519_PUBKEY_LEN);
+ tt_mem_op(key1.public_key,==, key3.public_key, CURVE25519_PUBKEY_LEN);
/* Now try bogus parses. */
strlcpy(buf, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$=", sizeof(buf));
@@ -1122,10 +1482,10 @@ test_crypto_curve25519_persist(void *arg)
tt_str_op(tag,==,"testing");
tor_free(tag);
- test_memeq(keypair.pubkey.public_key,
+ tt_mem_op(keypair.pubkey.public_key,==,
keypair2.pubkey.public_key,
CURVE25519_PUBKEY_LEN);
- test_memeq(keypair.seckey.secret_key,
+ tt_mem_op(keypair.seckey.secret_key,==,
keypair2.seckey.secret_key,
CURVE25519_SECKEY_LEN);
@@ -1137,11 +1497,11 @@ test_crypto_curve25519_persist(void *arg)
tt_assert(fast_memeq(content, "== c25519v1: testing ==", taglen));
tt_assert(tor_mem_is_zero(content+taglen, 32-taglen));
cp = content + 32;
- test_memeq(keypair.seckey.secret_key,
+ tt_mem_op(keypair.seckey.secret_key,==,
cp,
CURVE25519_SECKEY_LEN);
cp += CURVE25519_SECKEY_LEN;
- test_memeq(keypair.pubkey.public_key,
+ tt_mem_op(keypair.pubkey.public_key,==,
cp,
CURVE25519_SECKEY_LEN);
@@ -1161,7 +1521,362 @@ test_crypto_curve25519_persist(void *arg)
tor_free(tag);
}
-#endif
+static void
+test_crypto_ed25519_simple(void *arg)
+{
+ ed25519_keypair_t kp1, kp2;
+ ed25519_public_key_t pub1, pub2;
+ ed25519_secret_key_t sec1, sec2;
+ ed25519_signature_t sig1, sig2;
+ const uint8_t msg[] =
+ "GNU will be able to run Unix programs, "
+ "but will not be identical to Unix.";
+ const uint8_t msg2[] =
+ "Microsoft Windows extends the features of the DOS operating system, "
+ "yet is compatible with most existing applications that run under DOS.";
+ size_t msg_len = strlen((const char*)msg);
+ size_t msg2_len = strlen((const char*)msg2);
+
+ (void)arg;
+
+ tt_int_op(0, ==, ed25519_secret_key_generate(&sec1, 0));
+ tt_int_op(0, ==, ed25519_secret_key_generate(&sec2, 1));
+
+ tt_int_op(0, ==, ed25519_public_key_generate(&pub1, &sec1));
+ tt_int_op(0, ==, ed25519_public_key_generate(&pub2, &sec1));
+
+ tt_mem_op(pub1.pubkey, ==, pub2.pubkey, sizeof(pub1.pubkey));
+
+ memcpy(&kp1.pubkey, &pub1, sizeof(pub1));
+ memcpy(&kp1.seckey, &sec1, sizeof(sec1));
+ tt_int_op(0, ==, ed25519_sign(&sig1, msg, msg_len, &kp1));
+ tt_int_op(0, ==, ed25519_sign(&sig2, msg, msg_len, &kp1));
+
+ /* Ed25519 signatures are deterministic */
+ tt_mem_op(sig1.sig, ==, sig2.sig, sizeof(sig1.sig));
+
+ /* Basic signature is valid. */
+ tt_int_op(0, ==, ed25519_checksig(&sig1, msg, msg_len, &pub1));
+
+ /* Altered signature doesn't work. */
+ sig1.sig[0] ^= 3;
+ tt_int_op(-1, ==, ed25519_checksig(&sig1, msg, msg_len, &pub1));
+
+ /* Wrong public key doesn't work. */
+ tt_int_op(0, ==, ed25519_public_key_generate(&pub2, &sec2));
+ tt_int_op(-1, ==, ed25519_checksig(&sig2, msg, msg_len, &pub2));
+
+ /* Wrong message doesn't work. */
+ tt_int_op(0, ==, ed25519_checksig(&sig2, msg, msg_len, &pub1));
+ tt_int_op(-1, ==, ed25519_checksig(&sig2, msg, msg_len-1, &pub1));
+ tt_int_op(-1, ==, ed25519_checksig(&sig2, msg2, msg2_len, &pub1));
+
+ /* Batch signature checking works with some bad. */
+ tt_int_op(0, ==, ed25519_keypair_generate(&kp2, 0));
+ tt_int_op(0, ==, ed25519_sign(&sig1, msg, msg_len, &kp2));
+ {
+ ed25519_checkable_t ch[] = {
+ { &pub1, sig2, msg, msg_len }, /*ok*/
+ { &pub1, sig2, msg, msg_len-1 }, /*bad*/
+ { &kp2.pubkey, sig2, msg2, msg2_len }, /*bad*/
+ { &kp2.pubkey, sig1, msg, msg_len }, /*ok*/
+ };
+ int okay[4];
+ tt_int_op(-2, ==, ed25519_checksig_batch(okay, ch, 4));
+ tt_int_op(okay[0], ==, 1);
+ tt_int_op(okay[1], ==, 0);
+ tt_int_op(okay[2], ==, 0);
+ tt_int_op(okay[3], ==, 1);
+ tt_int_op(-2, ==, ed25519_checksig_batch(NULL, ch, 4));
+ }
+
+ /* Batch signature checking works with all good. */
+ {
+ ed25519_checkable_t ch[] = {
+ { &pub1, sig2, msg, msg_len }, /*ok*/
+ { &kp2.pubkey, sig1, msg, msg_len }, /*ok*/
+ };
+ int okay[2];
+ tt_int_op(0, ==, ed25519_checksig_batch(okay, ch, 2));
+ tt_int_op(okay[0], ==, 1);
+ tt_int_op(okay[1], ==, 1);
+ tt_int_op(0, ==, ed25519_checksig_batch(NULL, ch, 2));
+ }
+
+ done:
+ ;
+}
+
+static void
+test_crypto_ed25519_test_vectors(void *arg)
+{
+ char *mem_op_hex_tmp=NULL;
+ int i;
+ struct {
+ const char *sk;
+ const char *pk;
+ const char *sig;
+ const char *msg;
+ } items[] = {
+ /* These test vectors were generated with the "ref" implementation of
+ * ed25519 from SUPERCOP-20130419 */
+ { "4c6574277320686f706520746865726520617265206e6f206275677320696e20",
+ "f3e0e493b30f56e501aeb868fc912fe0c8b76621efca47a78f6d75875193dd87",
+ "b5d7fd6fd3adf643647ce1fe87a2931dedd1a4e38e6c662bedd35cdd80bfac51"
+ "1b2c7d1ee6bd929ac213014e1a8dc5373854c7b25dbe15ec96bf6c94196fae06",
+ "506c6561736520657863757365206d7920667269656e642e2048652069736e2774"
+ "204e554c2d7465726d696e617465642e"
+ },
+
+ { "74686520696d706c656d656e746174696f6e20776869636820617265206e6f74",
+ "407f0025a1e1351a4cb68e92f5c0ebaf66e7aaf93a4006a4d1a66e3ede1cfeac",
+ "02884fde1c3c5944d0ecf2d133726fc820c303aae695adceabf3a1e01e95bf28"
+ "da88c0966f5265e9c6f8edc77b3b96b5c91baec3ca993ccd21a3f64203600601",
+ "506c6561736520657863757365206d7920667269656e642e2048652069736e2774"
+ "204e554c2d7465726d696e617465642e"
+ },
+ { "6578706f73656420627920456e676c697368207465787420617320696e707574",
+ "61681cb5fbd69f9bc5a462a21a7ab319011237b940bc781cdc47fcbe327e7706",
+ "6a127d0414de7510125d4bc214994ffb9b8857a46330832d05d1355e882344ad"
+ "f4137e3ca1f13eb9cc75c887ef2309b98c57528b4acd9f6376c6898889603209",
+ "506c6561736520657863757365206d7920667269656e642e2048652069736e2774"
+ "204e554c2d7465726d696e617465642e"
+ },
+
+ /* These come from "sign.input" in ed25519's page */
+ { "5b5a619f8ce1c66d7ce26e5a2ae7b0c04febcd346d286c929e19d0d5973bfef9",
+ "6fe83693d011d111131c4f3fbaaa40a9d3d76b30012ff73bb0e39ec27ab18257",
+ "0f9ad9793033a2fa06614b277d37381e6d94f65ac2a5a94558d09ed6ce922258"
+ "c1a567952e863ac94297aec3c0d0c8ddf71084e504860bb6ba27449b55adc40e",
+ "5a8d9d0a22357e6655f9c785"
+ },
+ { "940c89fe40a81dafbdb2416d14ae469119869744410c3303bfaa0241dac57800",
+ "a2eb8c0501e30bae0cf842d2bde8dec7386f6b7fc3981b8c57c9792bb94cf2dd",
+ "d8bb64aad8c9955a115a793addd24f7f2b077648714f49c4694ec995b330d09d"
+ "640df310f447fd7b6cb5c14f9fe9f490bcf8cfadbfd2169c8ac20d3b8af49a0c",
+ "b87d3813e03f58cf19fd0b6395"
+ },
+ { "9acad959d216212d789a119252ebfe0c96512a23c73bd9f3b202292d6916a738",
+ "cf3af898467a5b7a52d33d53bc037e2642a8da996903fc252217e9c033e2f291",
+ "6ee3fe81e23c60eb2312b2006b3b25e6838e02106623f844c44edb8dafd66ab0"
+ "671087fd195df5b8f58a1d6e52af42908053d55c7321010092748795ef94cf06",
+ "55c7fa434f5ed8cdec2b7aeac173",
+ },
+ { "d5aeee41eeb0e9d1bf8337f939587ebe296161e6bf5209f591ec939e1440c300",
+ "fd2a565723163e29f53c9de3d5e8fbe36a7ab66e1439ec4eae9c0a604af291a5",
+ "f68d04847e5b249737899c014d31c805c5007a62c0a10d50bb1538c5f3550395"
+ "1fbc1e08682f2cc0c92efe8f4985dec61dcbd54d4b94a22547d24451271c8b00",
+ "0a688e79be24f866286d4646b5d81c"
+ },
+
+ { NULL, NULL, NULL, NULL}
+ };
+
+ (void)arg;
+
+ for (i = 0; items[i].pk; ++i) {
+ ed25519_keypair_t kp;
+ ed25519_signature_t sig;
+ uint8_t sk_seed[32];
+ uint8_t *msg;
+ size_t msg_len;
+ base16_decode((char*)sk_seed, sizeof(sk_seed),
+ items[i].sk, 64);
+ ed25519_secret_key_from_seed(&kp.seckey, sk_seed);
+ tt_int_op(0, ==, ed25519_public_key_generate(&kp.pubkey, &kp.seckey));
+ test_memeq_hex(kp.pubkey.pubkey, items[i].pk);
+
+ msg_len = strlen(items[i].msg) / 2;
+ msg = tor_malloc(msg_len);
+ base16_decode((char*)msg, msg_len, items[i].msg, strlen(items[i].msg));
+
+ tt_int_op(0, ==, ed25519_sign(&sig, msg, msg_len, &kp));
+ test_memeq_hex(sig.sig, items[i].sig);
+
+ tor_free(msg);
+ }
+
+ done:
+ tor_free(mem_op_hex_tmp);
+}
+
+static void
+test_crypto_ed25519_encode(void *arg)
+{
+ char buf[ED25519_BASE64_LEN+1];
+ ed25519_keypair_t kp;
+ ed25519_public_key_t pk;
+ char *mem_op_hex_tmp = NULL;
+ (void) arg;
+
+ /* Test roundtrip. */
+ tt_int_op(0, ==, ed25519_keypair_generate(&kp, 0));
+ tt_int_op(0, ==, ed25519_public_to_base64(buf, &kp.pubkey));
+ tt_int_op(ED25519_BASE64_LEN, ==, strlen(buf));
+ tt_int_op(0, ==, ed25519_public_from_base64(&pk, buf));
+ tt_mem_op(kp.pubkey.pubkey, ==, pk.pubkey, ED25519_PUBKEY_LEN);
+
+ /* Test known value. */
+ tt_int_op(0, ==, ed25519_public_from_base64(&pk,
+ "lVIuIctLjbGZGU5wKMNXxXlSE3cW4kaqkqm04u6pxvM"));
+ test_memeq_hex(pk.pubkey,
+ "95522e21cb4b8db199194e7028c357c57952137716e246aa92a9b4e2eea9c6f3");
+
+ done:
+ tor_free(mem_op_hex_tmp);
+}
+
+static void
+test_crypto_ed25519_convert(void *arg)
+{
+ const uint8_t msg[] =
+ "The eyes are not here / There are no eyes here.";
+ const int N = 30;
+ int i;
+ (void)arg;
+
+ for (i = 0; i < N; ++i) {
+ curve25519_keypair_t curve25519_keypair;
+ ed25519_keypair_t ed25519_keypair;
+ ed25519_public_key_t ed25519_pubkey;
+
+ int bit=0;
+ ed25519_signature_t sig;
+
+ tt_int_op(0,==,curve25519_keypair_generate(&curve25519_keypair, i&1));
+ tt_int_op(0,==,ed25519_keypair_from_curve25519_keypair(
+ &ed25519_keypair, &bit, &curve25519_keypair));
+ tt_int_op(0,==,ed25519_public_key_from_curve25519_public_key(
+ &ed25519_pubkey, &curve25519_keypair.pubkey, bit));
+ tt_mem_op(ed25519_pubkey.pubkey, ==, ed25519_keypair.pubkey.pubkey, 32);
+
+ tt_int_op(0,==,ed25519_sign(&sig, msg, sizeof(msg), &ed25519_keypair));
+ tt_int_op(0,==,ed25519_checksig(&sig, msg, sizeof(msg),
+ &ed25519_pubkey));
+
+ tt_int_op(-1,==,ed25519_checksig(&sig, msg, sizeof(msg)-1,
+ &ed25519_pubkey));
+ sig.sig[0] ^= 15;
+ tt_int_op(-1,==,ed25519_checksig(&sig, msg, sizeof(msg),
+ &ed25519_pubkey));
+ }
+
+ done:
+ ;
+}
+
+static void
+test_crypto_ed25519_blinding(void *arg)
+{
+ const uint8_t msg[] =
+ "Eyes I dare not meet in dreams / In death's dream kingdom";
+
+ const int N = 30;
+ int i;
+ (void)arg;
+
+ for (i = 0; i < N; ++i) {
+ uint8_t blinding[32];
+ ed25519_keypair_t ed25519_keypair;
+ ed25519_keypair_t ed25519_keypair_blinded;
+ ed25519_public_key_t ed25519_pubkey_blinded;
+
+ ed25519_signature_t sig;
+
+ crypto_rand((char*) blinding, sizeof(blinding));
+
+ tt_int_op(0,==,ed25519_keypair_generate(&ed25519_keypair, 0));
+ tt_int_op(0,==,ed25519_keypair_blind(&ed25519_keypair_blinded,
+ &ed25519_keypair, blinding));
+
+ tt_int_op(0,==,ed25519_public_blind(&ed25519_pubkey_blinded,
+ &ed25519_keypair.pubkey, blinding));
+
+ tt_mem_op(ed25519_pubkey_blinded.pubkey, ==,
+ ed25519_keypair_blinded.pubkey.pubkey, 32);
+
+ tt_int_op(0,==,ed25519_sign(&sig, msg, sizeof(msg),
+ &ed25519_keypair_blinded));
+
+ tt_int_op(0,==,ed25519_checksig(&sig, msg, sizeof(msg),
+ &ed25519_pubkey_blinded));
+
+ tt_int_op(-1,==,ed25519_checksig(&sig, msg, sizeof(msg)-1,
+ &ed25519_pubkey_blinded));
+ sig.sig[0] ^= 15;
+ tt_int_op(-1,==,ed25519_checksig(&sig, msg, sizeof(msg),
+ &ed25519_pubkey_blinded));
+ }
+
+ done:
+ ;
+}
+
+static void
+test_crypto_ed25519_testvectors(void *arg)
+{
+ unsigned i;
+ char *mem_op_hex_tmp = NULL;
+ (void)arg;
+
+ for (i = 0; i < ARRAY_LENGTH(ED25519_SECRET_KEYS); ++i) {
+ uint8_t sk[32];
+ ed25519_secret_key_t esk;
+ ed25519_public_key_t pk, blind_pk, pkfromcurve;
+ ed25519_keypair_t keypair, blind_keypair;
+ curve25519_keypair_t curvekp;
+ uint8_t blinding_param[32];
+ ed25519_signature_t sig;
+ int sign;
+
+#define DECODE(p,s) base16_decode((char*)(p),sizeof(p),(s),strlen(s))
+#define EQ(a,h) test_memeq_hex((const char*)(a), (h))
+
+ tt_int_op(0, ==, DECODE(sk, ED25519_SECRET_KEYS[i]));
+ tt_int_op(0, ==, DECODE(blinding_param, ED25519_BLINDING_PARAMS[i]));
+
+ tt_int_op(0, ==, ed25519_secret_key_from_seed(&esk, sk));
+ EQ(esk.seckey, ED25519_EXPANDED_SECRET_KEYS[i]);
+
+ tt_int_op(0, ==, ed25519_public_key_generate(&pk, &esk));
+ EQ(pk.pubkey, ED25519_PUBLIC_KEYS[i]);
+
+ memcpy(&curvekp.seckey.secret_key, esk.seckey, 32);
+ curve25519_public_key_generate(&curvekp.pubkey, &curvekp.seckey);
+
+ tt_int_op(0, ==,
+ ed25519_keypair_from_curve25519_keypair(&keypair, &sign, &curvekp));
+ tt_int_op(0, ==, ed25519_public_key_from_curve25519_public_key(
+ &pkfromcurve, &curvekp.pubkey, sign));
+ tt_mem_op(keypair.pubkey.pubkey, ==, pkfromcurve.pubkey, 32);
+ EQ(curvekp.pubkey.public_key, ED25519_CURVE25519_PUBLIC_KEYS[i]);
+
+ /* Self-signing */
+ memcpy(&keypair.seckey, &esk, sizeof(esk));
+ memcpy(&keypair.pubkey, &pk, sizeof(pk));
+
+ tt_int_op(0, ==, ed25519_sign(&sig, pk.pubkey, 32, &keypair));
+
+ EQ(sig.sig, ED25519_SELF_SIGNATURES[i]);
+
+ /* Blinding */
+ tt_int_op(0, ==,
+ ed25519_keypair_blind(&blind_keypair, &keypair, blinding_param));
+ tt_int_op(0, ==,
+ ed25519_public_blind(&blind_pk, &pk, blinding_param));
+
+ EQ(blind_keypair.seckey.seckey, ED25519_BLINDED_SECRET_KEYS[i]);
+ EQ(blind_pk.pubkey, ED25519_BLINDED_PUBLIC_KEYS[i]);
+
+ tt_mem_op(blind_pk.pubkey, ==, blind_keypair.pubkey.pubkey, 32);
+
+#undef DECODE
+#undef EQ
+ }
+ done:
+ tor_free(mem_op_hex_tmp);
+}
+#endif /* CURVE25519_ENABLED */
static void
test_crypto_siphash(void *arg)
@@ -1276,7 +1991,7 @@ static const struct testcase_setup_t pass_data = {
};
#define CRYPTO_LEGACY(name) \
- { #name, legacy_test_helper, 0, &legacy_setup, test_crypto_ ## name }
+ { #name, test_crypto_ ## name , 0, NULL, NULL }
struct testcase_t crypto_tests[] = {
CRYPTO_LEGACY(formats),
@@ -1288,7 +2003,23 @@ struct testcase_t crypto_tests[] = {
{ "pk_fingerprints", test_crypto_pk_fingerprints, TT_FORK, NULL, NULL },
CRYPTO_LEGACY(digests),
CRYPTO_LEGACY(dh),
- CRYPTO_LEGACY(s2k),
+ CRYPTO_LEGACY(s2k_rfc2440),
+#ifdef HAVE_LIBSCRYPT_H
+ { "s2k_scrypt", test_crypto_s2k_general, 0, &pass_data,
+ (void*)"scrypt" },
+ { "s2k_scrypt_low", test_crypto_s2k_general, 0, &pass_data,
+ (void*)"scrypt-low" },
+#endif
+ { "s2k_pbkdf2", test_crypto_s2k_general, 0, &pass_data,
+ (void*)"pbkdf2" },
+ { "s2k_rfc2440_general", test_crypto_s2k_general, 0, &pass_data,
+ (void*)"rfc2440" },
+ { "s2k_rfc2440_legacy", test_crypto_s2k_general, 0, &pass_data,
+ (void*)"rfc2440-legacy" },
+ { "s2k_errors", test_crypto_s2k_errors, 0, NULL, NULL },
+ { "scrypt_vectors", test_crypto_scrypt_vectors, 0, NULL, NULL },
+ { "pbkdf2_vectors", test_crypto_pbkdf2_vectors, 0, NULL, NULL },
+ { "pwbox", test_crypto_pwbox, 0, NULL, NULL },
{ "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &pass_data, (void*)"aes" },
{ "aes_iv_EVP", test_crypto_aes_iv, TT_FORK, &pass_data, (void*)"evp" },
CRYPTO_LEGACY(base32_decode),
@@ -1300,6 +2031,12 @@ struct testcase_t crypto_tests[] = {
{ "curve25519_wrappers", test_crypto_curve25519_wrappers, 0, NULL, NULL },
{ "curve25519_encode", test_crypto_curve25519_encode, 0, NULL, NULL },
{ "curve25519_persist", test_crypto_curve25519_persist, 0, NULL, NULL },
+ { "ed25519_simple", test_crypto_ed25519_simple, 0, NULL, NULL },
+ { "ed25519_test_vectors", test_crypto_ed25519_test_vectors, 0, NULL, NULL },
+ { "ed25519_encode", test_crypto_ed25519_encode, 0, NULL, NULL },
+ { "ed25519_convert", test_crypto_ed25519_convert, 0, NULL, NULL },
+ { "ed25519_blinding", test_crypto_ed25519_blinding, 0, NULL, NULL },
+ { "ed25519_testvectors", test_crypto_ed25519_testvectors, 0, NULL, NULL },
#endif
{ "siphash", test_crypto_siphash, 0, NULL, NULL },
END_OF_TESTCASES
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index c5eee46979..e03efbeff5 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -25,55 +25,56 @@
#include "test.h"
static void
-test_dir_nicknames(void)
+test_dir_nicknames(void *arg)
{
- test_assert( is_legal_nickname("a"));
- test_assert(!is_legal_nickname(""));
- test_assert(!is_legal_nickname("abcdefghijklmnopqrst")); /* 20 chars */
- test_assert(!is_legal_nickname("hyphen-")); /* bad char */
- test_assert( is_legal_nickname("abcdefghijklmnopqrs")); /* 19 chars */
- test_assert(!is_legal_nickname("$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA"));
+ (void)arg;
+ tt_assert( is_legal_nickname("a"));
+ tt_assert(!is_legal_nickname(""));
+ tt_assert(!is_legal_nickname("abcdefghijklmnopqrst")); /* 20 chars */
+ tt_assert(!is_legal_nickname("hyphen-")); /* bad char */
+ tt_assert( is_legal_nickname("abcdefghijklmnopqrs")); /* 19 chars */
+ tt_assert(!is_legal_nickname("$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA"));
/* valid */
- test_assert( is_legal_nickname_or_hexdigest(
+ tt_assert( is_legal_nickname_or_hexdigest(
"$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA"));
- test_assert( is_legal_nickname_or_hexdigest(
+ tt_assert( is_legal_nickname_or_hexdigest(
"$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA=fred"));
- test_assert( is_legal_nickname_or_hexdigest(
+ tt_assert( is_legal_nickname_or_hexdigest(
"$AAAAAAAA01234AAAAAAAAAAAAAAAAAAAAAAAAAAA~fred"));
/* too short */
- test_assert(!is_legal_nickname_or_hexdigest(
+ tt_assert(!is_legal_nickname_or_hexdigest(
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
/* illegal char */
- test_assert(!is_legal_nickname_or_hexdigest(
+ tt_assert(!is_legal_nickname_or_hexdigest(
"$AAAAAAzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
/* hex part too long */
- test_assert(!is_legal_nickname_or_hexdigest(
+ tt_assert(!is_legal_nickname_or_hexdigest(
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
- test_assert(!is_legal_nickname_or_hexdigest(
+ tt_assert(!is_legal_nickname_or_hexdigest(
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=fred"));
/* Bad nickname */
- test_assert(!is_legal_nickname_or_hexdigest(
+ tt_assert(!is_legal_nickname_or_hexdigest(
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="));
- test_assert(!is_legal_nickname_or_hexdigest(
+ tt_assert(!is_legal_nickname_or_hexdigest(
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~"));
- test_assert(!is_legal_nickname_or_hexdigest(
+ tt_assert(!is_legal_nickname_or_hexdigest(
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~hyphen-"));
- test_assert(!is_legal_nickname_or_hexdigest(
+ tt_assert(!is_legal_nickname_or_hexdigest(
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~"
"abcdefghijklmnoppqrst"));
/* Bad extra char. */
- test_assert(!is_legal_nickname_or_hexdigest(
+ tt_assert(!is_legal_nickname_or_hexdigest(
"$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!"));
- test_assert(is_legal_nickname_or_hexdigest("xyzzy"));
- test_assert(is_legal_nickname_or_hexdigest("abcdefghijklmnopqrs"));
- test_assert(!is_legal_nickname_or_hexdigest("abcdefghijklmnopqrst"));
+ tt_assert(is_legal_nickname_or_hexdigest("xyzzy"));
+ tt_assert(is_legal_nickname_or_hexdigest("abcdefghijklmnopqrs"));
+ tt_assert(!is_legal_nickname_or_hexdigest("abcdefghijklmnopqrst"));
done:
;
}
/** Run unit tests for router descriptor generation logic. */
static void
-test_dir_formats(void)
+test_dir_formats(void *arg)
{
char *buf = NULL;
char buf2[8192];
@@ -89,10 +90,11 @@ test_dir_formats(void)
or_options_t *options = get_options_mutable();
const addr_policy_t *p;
+ (void)arg;
pk1 = pk_generate(0);
pk2 = pk_generate(1);
- test_assert(pk1 && pk2);
+ tt_assert(pk1 && pk2);
hibernate_set_state_for_testing_(HIBERNATE_STATE_LIVE);
@@ -140,9 +142,9 @@ test_dir_formats(void)
smartlist_add(r2->exit_policy, ex2);
r2->nickname = tor_strdup("Fred");
- test_assert(!crypto_pk_write_public_key_to_string(pk1, &pk1_str,
+ tt_assert(!crypto_pk_write_public_key_to_string(pk1, &pk1_str,
&pk1_str_len));
- test_assert(!crypto_pk_write_public_key_to_string(pk2 , &pk2_str,
+ tt_assert(!crypto_pk_write_public_key_to_string(pk2 , &pk2_str,
&pk2_str_len));
/* XXXX025 router_dump_to_string should really take this from ri.*/
@@ -150,7 +152,7 @@ test_dir_formats(void)
"<magri@elsewhere.example.com>");
buf = router_dump_router_to_string(r1, pk2);
tor_free(options->ContactInfo);
- test_assert(buf);
+ tt_assert(buf);
strlcpy(buf2, "router Magri 192.168.0.1 9000 0 9003\n"
"or-address [1:2:3:4::]:9999\n"
@@ -160,7 +162,7 @@ test_dir_formats(void)
"protocols Link 1 2 Circuit 1\n"
"published 1970-01-01 00:00:00\n"
"fingerprint ", sizeof(buf2));
- test_assert(!crypto_pk_get_fingerprint(pk2, fingerprint, 1));
+ tt_assert(!crypto_pk_get_fingerprint(pk2, fingerprint, 1));
strlcat(buf2, fingerprint, sizeof(buf2));
strlcat(buf2, "\nuptime 0\n"
/* XXX the "0" above is hard-coded, but even if we made it reflect
@@ -178,23 +180,23 @@ test_dir_formats(void)
buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same
* twice */
- test_streq(buf, buf2);
+ tt_str_op(buf,==, buf2);
tor_free(buf);
buf = router_dump_router_to_string(r1, pk2);
- test_assert(buf);
+ tt_assert(buf);
cp = buf;
- rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL);
- test_assert(rp1);
- test_eq(rp1->addr, r1->addr);
- test_eq(rp1->or_port, r1->or_port);
+ rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL);
+ tt_assert(rp1);
+ tt_int_op(rp1->addr,==, r1->addr);
+ tt_int_op(rp1->or_port,==, r1->or_port);
//test_eq(rp1->dir_port, r1->dir_port);
- test_eq(rp1->bandwidthrate, r1->bandwidthrate);
- test_eq(rp1->bandwidthburst, r1->bandwidthburst);
- test_eq(rp1->bandwidthcapacity, r1->bandwidthcapacity);
- test_assert(crypto_pk_cmp_keys(rp1->onion_pkey, pk1) == 0);
- test_assert(crypto_pk_cmp_keys(rp1->identity_pkey, pk2) == 0);
- //test_assert(rp1->exit_policy == NULL);
+ tt_int_op(rp1->bandwidthrate,==, r1->bandwidthrate);
+ tt_int_op(rp1->bandwidthburst,==, r1->bandwidthburst);
+ tt_int_op(rp1->bandwidthcapacity,==, r1->bandwidthcapacity);
+ tt_assert(crypto_pk_cmp_keys(rp1->onion_pkey, pk1) == 0);
+ tt_assert(crypto_pk_cmp_keys(rp1->identity_pkey, pk2) == 0);
+ //tt_assert(rp1->exit_policy == NULL);
tor_free(buf);
strlcpy(buf2,
@@ -205,7 +207,7 @@ test_dir_formats(void)
"protocols Link 1 2 Circuit 1\n"
"published 1970-01-01 00:00:05\n"
"fingerprint ", sizeof(buf2));
- test_assert(!crypto_pk_get_fingerprint(pk1, fingerprint, 1));
+ tt_assert(!crypto_pk_get_fingerprint(pk1, fingerprint, 1));
strlcat(buf2, fingerprint, sizeof(buf2));
strlcat(buf2, "\nuptime 0\n"
"bandwidth 3000 3000 3000\n", sizeof(buf2));
@@ -224,42 +226,42 @@ test_dir_formats(void)
buf = router_dump_router_to_string(r2, pk1);
buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same
* twice */
- test_streq(buf, buf2);
+ tt_str_op(buf,==, buf2);
tor_free(buf);
buf = router_dump_router_to_string(r2, pk1);
cp = buf;
- rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL);
- test_assert(rp2);
- test_eq(rp2->addr, r2->addr);
- test_eq(rp2->or_port, r2->or_port);
- test_eq(rp2->dir_port, r2->dir_port);
- test_eq(rp2->bandwidthrate, r2->bandwidthrate);
- test_eq(rp2->bandwidthburst, r2->bandwidthburst);
- test_eq(rp2->bandwidthcapacity, r2->bandwidthcapacity);
+ rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL);
+ tt_assert(rp2);
+ tt_int_op(rp2->addr,==, r2->addr);
+ tt_int_op(rp2->or_port,==, r2->or_port);
+ tt_int_op(rp2->dir_port,==, r2->dir_port);
+ tt_int_op(rp2->bandwidthrate,==, r2->bandwidthrate);
+ tt_int_op(rp2->bandwidthburst,==, r2->bandwidthburst);
+ tt_int_op(rp2->bandwidthcapacity,==, r2->bandwidthcapacity);
#ifdef CURVE25519_ENABLED
- test_memeq(rp2->onion_curve25519_pkey->public_key,
+ tt_mem_op(rp2->onion_curve25519_pkey->public_key,==,
r2->onion_curve25519_pkey->public_key,
CURVE25519_PUBKEY_LEN);
#endif
- test_assert(crypto_pk_cmp_keys(rp2->onion_pkey, pk2) == 0);
- test_assert(crypto_pk_cmp_keys(rp2->identity_pkey, pk1) == 0);
+ tt_assert(crypto_pk_cmp_keys(rp2->onion_pkey, pk2) == 0);
+ tt_assert(crypto_pk_cmp_keys(rp2->identity_pkey, pk1) == 0);
- test_eq(smartlist_len(rp2->exit_policy), 2);
+ tt_int_op(smartlist_len(rp2->exit_policy),==, 2);
p = smartlist_get(rp2->exit_policy, 0);
- test_eq(p->policy_type, ADDR_POLICY_ACCEPT);
- test_assert(tor_addr_is_null(&p->addr));
- test_eq(p->maskbits, 0);
- test_eq(p->prt_min, 80);
- test_eq(p->prt_max, 80);
+ tt_int_op(p->policy_type,==, ADDR_POLICY_ACCEPT);
+ tt_assert(tor_addr_is_null(&p->addr));
+ tt_int_op(p->maskbits,==, 0);
+ tt_int_op(p->prt_min,==, 80);
+ tt_int_op(p->prt_max,==, 80);
p = smartlist_get(rp2->exit_policy, 1);
- test_eq(p->policy_type, ADDR_POLICY_REJECT);
- test_assert(tor_addr_eq(&p->addr, &ex2->addr));
- test_eq(p->maskbits, 8);
- test_eq(p->prt_min, 24);
- test_eq(p->prt_max, 24);
+ tt_int_op(p->policy_type,==, ADDR_POLICY_REJECT);
+ tt_assert(tor_addr_eq(&p->addr, &ex2->addr));
+ tt_int_op(p->maskbits,==, 8);
+ tt_int_op(p->prt_min,==, 24);
+ tt_int_op(p->prt_max,==, 24);
#if 0
/* Okay, now for the directories. */
@@ -292,50 +294,551 @@ test_dir_formats(void)
tor_free(dir2); /* And more !*/
}
+#include "failing_routerdescs.inc"
+
+static void
+test_dir_routerparse_bad(void *arg)
+{
+ (void) arg;
+
+ int again;
+ routerinfo_t *ri = NULL;
+
+#define CHECK_OK(s) \
+ do { \
+ routerinfo_free(ri); \
+ ri = router_parse_entry_from_string((s), NULL, 0, 0, NULL, NULL); \
+ tt_assert(ri); \
+ } while (0)
+#define CHECK_FAIL(s, againval) \
+ do { \
+ routerinfo_free(ri); \
+ again = 999; \
+ ri = router_parse_entry_from_string((s), NULL, 0, 0, NULL, &again); \
+ tt_assert(ri == NULL); \
+ tt_int_op(again, ==, (againval)); \
+ } while (0)
+
+ CHECK_OK(EX_RI_MINIMAL);
+ CHECK_OK(EX_RI_MAXIMAL);
+
+ /* good annotations prepended */
+ routerinfo_free(ri);
+ ri = router_parse_entry_from_string(EX_RI_MINIMAL, NULL, 0, 0,
+ "@purpose bridge\n", NULL);
+ tt_assert(ri != NULL);
+ tt_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE);
+ routerinfo_free(ri);
+
+ /* bad annotations prepended. */
+ ri = router_parse_entry_from_string(EX_RI_MINIMAL,
+ NULL, 0, 0, "@purpose\n", NULL);
+ tt_assert(ri == NULL);
+
+ /* bad annotations on router. */
+ ri = router_parse_entry_from_string("@purpose\nrouter x\n", NULL, 0, 1,
+ NULL, NULL);
+ tt_assert(ri == NULL);
+
+ /* unwanted annotations on router. */
+ ri = router_parse_entry_from_string("@purpose foo\nrouter x\n", NULL, 0, 0,
+ NULL, NULL);
+ tt_assert(ri == NULL);
+
+ /* No signature. */
+ ri = router_parse_entry_from_string("router x\n", NULL, 0, 0,
+ NULL, NULL);
+ tt_assert(ri == NULL);
+
+ /* Not a router */
+ routerinfo_free(ri);
+ ri = router_parse_entry_from_string("hello\n", NULL, 0, 0, NULL, NULL);
+ tt_assert(ri == NULL);
+
+ CHECK_FAIL(EX_RI_BAD_SIG1, 1);
+ CHECK_FAIL(EX_RI_BAD_SIG2, 1);
+ CHECK_FAIL(EX_RI_BAD_TOKENS, 0);
+ CHECK_FAIL(EX_RI_BAD_PUBLISHED, 0);
+ CHECK_FAIL(EX_RI_NEG_BANDWIDTH, 0);
+ CHECK_FAIL(EX_RI_BAD_BANDWIDTH, 0);
+ CHECK_FAIL(EX_RI_BAD_BANDWIDTH2, 0);
+ CHECK_FAIL(EX_RI_BAD_ONIONKEY1, 0);
+ CHECK_FAIL(EX_RI_BAD_ONIONKEY2, 0);
+ CHECK_FAIL(EX_RI_BAD_PORTS, 0);
+ CHECK_FAIL(EX_RI_BAD_IP, 0);
+ CHECK_FAIL(EX_RI_BAD_DIRPORT, 0);
+ CHECK_FAIL(EX_RI_BAD_NAME2, 0);
+ CHECK_FAIL(EX_RI_BAD_UPTIME, 0);
+
+ CHECK_FAIL(EX_RI_BAD_BANDWIDTH3, 0);
+ CHECK_FAIL(EX_RI_BAD_NTOR_KEY, 0);
+ CHECK_FAIL(EX_RI_BAD_FINGERPRINT, 0);
+ CHECK_FAIL(EX_RI_MISMATCHED_FINGERPRINT, 0);
+ CHECK_FAIL(EX_RI_BAD_HAS_ACCEPT6, 0);
+ CHECK_FAIL(EX_RI_BAD_NO_EXIT_POLICY, 0);
+ CHECK_FAIL(EX_RI_BAD_IPV6_EXIT_POLICY, 0);
+ CHECK_FAIL(EX_RI_BAD_FAMILY, 0);
+ CHECK_FAIL(EX_RI_ZERO_ORPORT, 0);
+
+ /* This is allowed; we just ignore it. */
+ CHECK_OK(EX_RI_BAD_EI_DIGEST);
+
+#undef CHECK_FAIL
+#undef CHECK_OK
+ done:
+ routerinfo_free(ri);
+}
+
+#include "example_extrainfo.inc"
+
+static void
+test_dir_extrainfo_parsing(void *arg)
+{
+ (void) arg;
+
+#define CHECK_OK(s) \
+ do { \
+ extrainfo_free(ei); \
+ ei = extrainfo_parse_entry_from_string((s), NULL, 0, map, NULL); \
+ tt_assert(ei); \
+ } while (0)
+#define CHECK_FAIL(s, againval) \
+ do { \
+ extrainfo_free(ei); \
+ again = 999; \
+ ei = extrainfo_parse_entry_from_string((s), NULL, 0, map, &again); \
+ tt_assert(ei == NULL); \
+ tt_int_op(again, ==, (againval)); \
+ } while (0)
+#define ADD(name) \
+ do { \
+ ri = tor_malloc_zero(sizeof(routerinfo_t)); \
+ crypto_pk_t *pk = ri->identity_pkey = crypto_pk_new(); \
+ tt_assert(! crypto_pk_read_public_key_from_string(pk, \
+ name##_KEY, strlen(name##_KEY))); \
+ tt_int_op(0,==,base16_decode(d, 20, name##_FP, strlen(name##_FP))); \
+ digestmap_set((digestmap_t*)map, d, ri); \
+ ri = NULL; \
+ } while (0)
+
+ routerinfo_t *ri = NULL;
+ char d[20];
+ struct digest_ri_map_t *map = NULL;
+ extrainfo_t *ei = NULL;
+ int again;
+
+ CHECK_OK(EX_EI_MINIMAL);
+ tt_assert(ei->pending_sig);
+ CHECK_OK(EX_EI_MAXIMAL);
+ tt_assert(ei->pending_sig);
+
+ map = (struct digest_ri_map_t *)digestmap_new();
+ ADD(EX_EI_MINIMAL);
+ ADD(EX_EI_MAXIMAL);
+ ADD(EX_EI_BAD_FP);
+ ADD(EX_EI_BAD_NICKNAME);
+ ADD(EX_EI_BAD_TOKENS);
+ ADD(EX_EI_BAD_START);
+ ADD(EX_EI_BAD_PUBLISHED);
+
+ CHECK_OK(EX_EI_MINIMAL);
+ tt_assert(!ei->pending_sig);
+ CHECK_OK(EX_EI_MAXIMAL);
+ tt_assert(!ei->pending_sig);
+
+ CHECK_FAIL(EX_EI_BAD_SIG1,1);
+ CHECK_FAIL(EX_EI_BAD_SIG2,1);
+ CHECK_FAIL(EX_EI_BAD_SIG3,1);
+ CHECK_FAIL(EX_EI_BAD_FP,0);
+ CHECK_FAIL(EX_EI_BAD_NICKNAME,0);
+ CHECK_FAIL(EX_EI_BAD_TOKENS,0);
+ CHECK_FAIL(EX_EI_BAD_START,0);
+ CHECK_FAIL(EX_EI_BAD_PUBLISHED,0);
+
+#undef CHECK_OK
+#undef CHECK_FAIL
+
+ done:
+ routerinfo_free(ri);
+ /* XXXX elements should get freed too */
+ digestmap_free((digestmap_t*)map, NULL);
+}
+
+static void
+test_dir_parse_router_list(void *arg)
+{
+ (void) arg;
+ smartlist_t *invalid = smartlist_new();
+ smartlist_t *dest = smartlist_new();
+ smartlist_t *chunks = smartlist_new();
+ int dest_has_ri = 1;
+ char *list = NULL;
+ const char *cp;
+ digestmap_t *map = NULL;
+ char *mem_op_hex_tmp = NULL;
+ routerinfo_t *ri = NULL;
+ char d[DIGEST_LEN];
+
+ smartlist_add(chunks, tor_strdup(EX_RI_MINIMAL)); // ri 0
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_PORTS)); // bad ri 0
+ smartlist_add(chunks, tor_strdup(EX_EI_MAXIMAL)); // ei 0
+ smartlist_add(chunks, tor_strdup(EX_EI_BAD_SIG2)); // bad ei --
+ smartlist_add(chunks, tor_strdup(EX_EI_BAD_NICKNAME));// bad ei 0
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_SIG1)); // bad ri --
+ smartlist_add(chunks, tor_strdup(EX_EI_BAD_PUBLISHED)); // bad ei 1
+ smartlist_add(chunks, tor_strdup(EX_RI_MAXIMAL)); // ri 1
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_FAMILY)); // bad ri 1
+ smartlist_add(chunks, tor_strdup(EX_EI_MINIMAL)); // ei 1
+
+ list = smartlist_join_strings(chunks, "", 0, NULL);
+
+ /* First, parse the routers. */
+ cp = list;
+ tt_int_op(0,==,
+ router_parse_list_from_string(&cp, NULL, dest, SAVED_NOWHERE,
+ 0, 0, NULL, invalid));
+ tt_int_op(2, ==, smartlist_len(dest));
+ tt_ptr_op(cp, ==, list + strlen(list));
+
+ routerinfo_t *r = smartlist_get(dest, 0);
+ tt_mem_op(r->cache_info.signed_descriptor_body, ==,
+ EX_RI_MINIMAL, strlen(EX_RI_MINIMAL));
+ r = smartlist_get(dest, 1);
+ tt_mem_op(r->cache_info.signed_descriptor_body, ==,
+ EX_RI_MAXIMAL, strlen(EX_RI_MAXIMAL));
+
+ tt_int_op(2, ==, smartlist_len(invalid));
+ test_memeq_hex(smartlist_get(invalid, 0),
+ "ab9eeaa95e7d45740185b4e519c76ead756277a9");
+ test_memeq_hex(smartlist_get(invalid, 1),
+ "9a651ee03b64325959e8f1b46f2b689b30750b4c");
+
+ /* Now tidy up */
+ SMARTLIST_FOREACH(dest, routerinfo_t *, ri, routerinfo_free(ri));
+ SMARTLIST_FOREACH(invalid, uint8_t *, d, tor_free(d));
+ smartlist_clear(dest);
+ smartlist_clear(invalid);
+
+ /* And check extrainfos. */
+ dest_has_ri = 0;
+ map = (digestmap_t*)router_get_routerlist()->identity_map;
+ ADD(EX_EI_MINIMAL);
+ ADD(EX_EI_MAXIMAL);
+ ADD(EX_EI_BAD_NICKNAME);
+ ADD(EX_EI_BAD_PUBLISHED);
+ cp = list;
+ tt_int_op(0,==,
+ router_parse_list_from_string(&cp, NULL, dest, SAVED_NOWHERE,
+ 1, 0, NULL, invalid));
+ tt_int_op(2, ==, smartlist_len(dest));
+ extrainfo_t *e = smartlist_get(dest, 0);
+ tt_mem_op(e->cache_info.signed_descriptor_body, ==,
+ EX_EI_MAXIMAL, strlen(EX_EI_MAXIMAL));
+ e = smartlist_get(dest, 1);
+ tt_mem_op(e->cache_info.signed_descriptor_body, ==,
+ EX_EI_MINIMAL, strlen(EX_EI_MINIMAL));
+
+ tt_int_op(2, ==, smartlist_len(invalid));
+ test_memeq_hex(smartlist_get(invalid, 0),
+ "d5df4aa62ee9ffc9543d41150c9864908e0390af");
+ test_memeq_hex(smartlist_get(invalid, 1),
+ "f61efd2a7f4531f3687a9043e0de90a862ec64ba");
+
+ done:
+ tor_free(list);
+ if (dest_has_ri)
+ SMARTLIST_FOREACH(dest, routerinfo_t *, rt, routerinfo_free(rt));
+ else
+ SMARTLIST_FOREACH(dest, extrainfo_t *, ei, extrainfo_free(ei));
+ smartlist_free(dest);
+ SMARTLIST_FOREACH(invalid, uint8_t *, d, tor_free(d));
+ smartlist_free(invalid);
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_free(chunks);
+ routerinfo_free(ri);
+ /* XXXX this leaks: */
+ if (map) {
+ digestmap_free((digestmap_t*)map, NULL);
+ router_get_routerlist()->identity_map =
+ (struct digest_ri_map_t*)digestmap_new();
+ }
+ tor_free(mem_op_hex_tmp);
+
+#undef ADD
+}
+
+static download_status_t dls_minimal;
+static download_status_t dls_maximal;
+static download_status_t dls_bad_fingerprint;
+static download_status_t dls_bad_sig2;
+static download_status_t dls_bad_ports;
+static download_status_t dls_bad_tokens;
+
+static int mock_router_get_dl_status_unrecognized = 0;
+static int mock_router_get_dl_status_calls = 0;
+
+static download_status_t *
+mock_router_get_dl_status(const char *d)
+{
+ ++mock_router_get_dl_status_calls;
+ char hex[HEX_DIGEST_LEN+1];
+ base16_encode(hex, sizeof(hex), d, DIGEST_LEN);
+ if (!strcmp(hex, "3E31D19A69EB719C00B02EC60D13356E3F7A3452")) {
+ return &dls_minimal;
+ } else if (!strcmp(hex, "581D8A368A0FA854ECDBFAB841D88B3F1B004038")) {
+ return &dls_maximal;
+ } else if (!strcmp(hex, "2578AE227C6116CDE29B3F0E95709B9872DEE5F1")) {
+ return &dls_bad_fingerprint;
+ } else if (!strcmp(hex, "16D387D3A58F7DB3CF46638F8D0B90C45C7D769C")) {
+ return &dls_bad_sig2;
+ } else if (!strcmp(hex, "AB9EEAA95E7D45740185B4E519C76EAD756277A9")) {
+ return &dls_bad_ports;
+ } else if (!strcmp(hex, "A0CC2CEFAD59DBF19F468BFEE60E0868C804B422")) {
+ return &dls_bad_tokens;
+ } else {
+ ++mock_router_get_dl_status_unrecognized;
+ return NULL;
+ }
+}
+
+static void
+test_dir_load_routers(void *arg)
+{
+ (void) arg;
+ smartlist_t *chunks = smartlist_new();
+ smartlist_t *wanted = smartlist_new();
+ char buf[DIGEST_LEN];
+ char *mem_op_hex_tmp = NULL;
+
+#define ADD(str) \
+ do { \
+ tt_int_op(0,==,router_get_router_hash(str, strlen(str), buf)); \
+ smartlist_add(wanted, tor_strdup(hex_str(buf, DIGEST_LEN))); \
+ } while (0)
+
+ MOCK(router_get_dl_status_by_descriptor_digest, mock_router_get_dl_status);
+
+ update_approx_time(1412510400);
+
+ smartlist_add(chunks, tor_strdup(EX_RI_MINIMAL));
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_FINGERPRINT));
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_SIG2));
+ smartlist_add(chunks, tor_strdup(EX_RI_MAXIMAL));
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_PORTS));
+ smartlist_add(chunks, tor_strdup(EX_RI_BAD_TOKENS));
+
+ /* not ADDing MINIMIAL */
+ ADD(EX_RI_MAXIMAL);
+ ADD(EX_RI_BAD_FINGERPRINT);
+ ADD(EX_RI_BAD_SIG2);
+ /* Not ADDing BAD_PORTS */
+ ADD(EX_RI_BAD_TOKENS);
+
+ char *list = smartlist_join_strings(chunks, "", 0, NULL);
+ tt_int_op(1, ==,
+ router_load_routers_from_string(list, NULL, SAVED_IN_JOURNAL,
+ wanted, 1, NULL));
+
+ /* The "maximal" router was added. */
+ /* "minimal" was not. */
+ tt_int_op(smartlist_len(router_get_routerlist()->routers),==,1);
+ routerinfo_t *r = smartlist_get(router_get_routerlist()->routers, 0);
+ test_memeq_hex(r->cache_info.signed_descriptor_digest,
+ "581D8A368A0FA854ECDBFAB841D88B3F1B004038");
+ tt_int_op(dls_minimal.n_download_failures, ==, 0);
+ tt_int_op(dls_maximal.n_download_failures, ==, 0);
+
+ /* "Bad fingerprint" and "Bad tokens" should have gotten marked
+ * non-retriable. */
+ tt_want_int_op(mock_router_get_dl_status_calls, ==, 2);
+ tt_want_int_op(mock_router_get_dl_status_unrecognized, ==, 0);
+ tt_int_op(dls_bad_fingerprint.n_download_failures, ==, 255);
+ tt_int_op(dls_bad_tokens.n_download_failures, ==, 255);
+
+ /* bad_sig2 and bad ports" are retriable -- one since only the signature
+ * was bad, and one because we didn't ask for it. */
+ tt_int_op(dls_bad_sig2.n_download_failures, ==, 0);
+ tt_int_op(dls_bad_ports.n_download_failures, ==, 0);
+
+ /* Wanted still contains "BAD_SIG2" */
+ tt_int_op(smartlist_len(wanted), ==, 1);
+ tt_str_op(smartlist_get(wanted, 0), ==,
+ "E0A3753CEFD54128EAB239F294954121DB23D2EF");
+
+#undef ADD
+
+ done:
+ tor_free(mem_op_hex_tmp);
+ UNMOCK(router_get_dl_status_by_descriptor_digest);
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_free(chunks);
+ SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
+ smartlist_free(wanted);
+}
+
+static int mock_get_by_ei_dd_calls = 0;
+static int mock_get_by_ei_dd_unrecognized = 0;
+
+static signed_descriptor_t sd_ei_minimal;
+static signed_descriptor_t sd_ei_bad_nickname;
+static signed_descriptor_t sd_ei_maximal;
+static signed_descriptor_t sd_ei_bad_tokens;
+static signed_descriptor_t sd_ei_bad_sig2;
+
+static signed_descriptor_t *
+mock_get_by_ei_desc_digest(const char *d)
+{
+
+ ++mock_get_by_ei_dd_calls;
+ char hex[HEX_DIGEST_LEN+1];
+ base16_encode(hex, sizeof(hex), d, DIGEST_LEN);
+
+ if (!strcmp(hex, "11E0EDF526950739F7769810FCACAB8C882FAEEE")) {
+ return &sd_ei_minimal;
+ } else if (!strcmp(hex, "47803B02A0E70E9E8BDA226CB1D74DE354D67DFF")) {
+ return &sd_ei_maximal;
+ } else if (!strcmp(hex, "D5DF4AA62EE9FFC9543D41150C9864908E0390AF")) {
+ return &sd_ei_bad_nickname;
+ } else if (!strcmp(hex, "16D387D3A58F7DB3CF46638F8D0B90C45C7D769C")) {
+ return &sd_ei_bad_sig2;
+ } else if (!strcmp(hex, "9D90F8C42955BBC57D54FB05E54A3F083AF42E8B")) {
+ return &sd_ei_bad_tokens;
+ } else {
+ ++mock_get_by_ei_dd_unrecognized;
+ return NULL;
+ }
+}
+
+static smartlist_t *mock_ei_insert_list = NULL;
+static was_router_added_t
+mock_ei_insert(routerlist_t *rl, extrainfo_t *ei)
+{
+ (void) rl;
+ smartlist_add(mock_ei_insert_list, ei);
+ return ROUTER_ADDED_SUCCESSFULLY;
+}
+
static void
-test_dir_versions(void)
+test_dir_load_extrainfo(void *arg)
+{
+ (void) arg;
+ smartlist_t *chunks = smartlist_new();
+ smartlist_t *wanted = smartlist_new();
+ char buf[DIGEST_LEN];
+ char *mem_op_hex_tmp = NULL;
+
+#define ADD(str) \
+ do { \
+ tt_int_op(0,==,router_get_extrainfo_hash(str, strlen(str), buf)); \
+ smartlist_add(wanted, tor_strdup(hex_str(buf, DIGEST_LEN))); \
+ } while (0)
+
+ mock_ei_insert_list = smartlist_new();
+ MOCK(router_get_by_extrainfo_digest, mock_get_by_ei_desc_digest);
+ MOCK(extrainfo_insert, mock_ei_insert);
+
+ smartlist_add(chunks, tor_strdup(EX_EI_MINIMAL));
+ smartlist_add(chunks, tor_strdup(EX_EI_BAD_NICKNAME));
+ smartlist_add(chunks, tor_strdup(EX_EI_MAXIMAL));
+ smartlist_add(chunks, tor_strdup(EX_EI_BAD_PUBLISHED));
+ smartlist_add(chunks, tor_strdup(EX_EI_BAD_TOKENS));
+
+ /* not ADDing MINIMIAL */
+ ADD(EX_EI_MAXIMAL);
+ ADD(EX_EI_BAD_NICKNAME);
+ /* Not ADDing BAD_PUBLISHED */
+ ADD(EX_EI_BAD_TOKENS);
+ ADD(EX_EI_BAD_SIG2);
+
+ char *list = smartlist_join_strings(chunks, "", 0, NULL);
+ router_load_extrainfo_from_string(list, NULL, SAVED_IN_JOURNAL, wanted, 1);
+
+ /* The "maximal" router was added. */
+ /* "minimal" was also added, even though we didn't ask for it, since
+ * that's what we do with extrainfos. */
+ tt_int_op(smartlist_len(mock_ei_insert_list),==,2);
+
+ extrainfo_t *e = smartlist_get(mock_ei_insert_list, 0);
+ test_memeq_hex(e->cache_info.signed_descriptor_digest,
+ "11E0EDF526950739F7769810FCACAB8C882FAEEE");
+
+ e = smartlist_get(mock_ei_insert_list, 1);
+ test_memeq_hex(e->cache_info.signed_descriptor_digest,
+ "47803B02A0E70E9E8BDA226CB1D74DE354D67DFF");
+ tt_int_op(dls_minimal.n_download_failures, ==, 0);
+ tt_int_op(dls_maximal.n_download_failures, ==, 0);
+
+ /* "Bad nickname" and "Bad tokens" should have gotten marked
+ * non-retriable. */
+ tt_want_int_op(mock_get_by_ei_dd_calls, ==, 2);
+ tt_want_int_op(mock_get_by_ei_dd_unrecognized, ==, 0);
+ tt_int_op(sd_ei_bad_nickname.ei_dl_status.n_download_failures, ==, 255);
+ tt_int_op(sd_ei_bad_tokens.ei_dl_status.n_download_failures, ==, 255);
+
+ /* bad_ports is retriable -- because we didn't ask for it. */
+ tt_int_op(dls_bad_ports.n_download_failures, ==, 0);
+
+ /* Wanted still contains "BAD_SIG2" */
+ tt_int_op(smartlist_len(wanted), ==, 1);
+ tt_str_op(smartlist_get(wanted, 0), ==,
+ "16D387D3A58F7DB3CF46638F8D0B90C45C7D769C");
+
+#undef ADD
+
+ done:
+ tor_free(mem_op_hex_tmp);
+ UNMOCK(router_get_by_extrainfo_digest);
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_free(chunks);
+ SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
+ smartlist_free(wanted);
+}
+
+static void
+test_dir_versions(void *arg)
{
tor_version_t ver1;
/* Try out version parsing functionality */
- test_eq(0, tor_version_parse("0.3.4pre2-cvs", &ver1));
- test_eq(0, ver1.major);
- test_eq(3, ver1.minor);
- test_eq(4, ver1.micro);
- test_eq(VER_PRE, ver1.status);
- test_eq(2, ver1.patchlevel);
- test_eq(0, tor_version_parse("0.3.4rc1", &ver1));
- test_eq(0, ver1.major);
- test_eq(3, ver1.minor);
- test_eq(4, ver1.micro);
- test_eq(VER_RC, ver1.status);
- test_eq(1, ver1.patchlevel);
- test_eq(0, tor_version_parse("1.3.4", &ver1));
- test_eq(1, ver1.major);
- test_eq(3, ver1.minor);
- test_eq(4, ver1.micro);
- test_eq(VER_RELEASE, ver1.status);
- test_eq(0, ver1.patchlevel);
- test_eq(0, tor_version_parse("1.3.4.999", &ver1));
- test_eq(1, ver1.major);
- test_eq(3, ver1.minor);
- test_eq(4, ver1.micro);
- test_eq(VER_RELEASE, ver1.status);
- test_eq(999, ver1.patchlevel);
- test_eq(0, tor_version_parse("0.1.2.4-alpha", &ver1));
- test_eq(0, ver1.major);
- test_eq(1, ver1.minor);
- test_eq(2, ver1.micro);
- test_eq(4, ver1.patchlevel);
- test_eq(VER_RELEASE, ver1.status);
- test_streq("alpha", ver1.status_tag);
- test_eq(0, tor_version_parse("0.1.2.4", &ver1));
- test_eq(0, ver1.major);
- test_eq(1, ver1.minor);
- test_eq(2, ver1.micro);
- test_eq(4, ver1.patchlevel);
- test_eq(VER_RELEASE, ver1.status);
- test_streq("", ver1.status_tag);
+ (void)arg;
+ tt_int_op(0,==, tor_version_parse("0.3.4pre2-cvs", &ver1));
+ tt_int_op(0,==, ver1.major);
+ tt_int_op(3,==, ver1.minor);
+ tt_int_op(4,==, ver1.micro);
+ tt_int_op(VER_PRE,==, ver1.status);
+ tt_int_op(2,==, ver1.patchlevel);
+ tt_int_op(0,==, tor_version_parse("0.3.4rc1", &ver1));
+ tt_int_op(0,==, ver1.major);
+ tt_int_op(3,==, ver1.minor);
+ tt_int_op(4,==, ver1.micro);
+ tt_int_op(VER_RC,==, ver1.status);
+ tt_int_op(1,==, ver1.patchlevel);
+ tt_int_op(0,==, tor_version_parse("1.3.4", &ver1));
+ tt_int_op(1,==, ver1.major);
+ tt_int_op(3,==, ver1.minor);
+ tt_int_op(4,==, ver1.micro);
+ tt_int_op(VER_RELEASE,==, ver1.status);
+ tt_int_op(0,==, ver1.patchlevel);
+ tt_int_op(0,==, tor_version_parse("1.3.4.999", &ver1));
+ tt_int_op(1,==, ver1.major);
+ tt_int_op(3,==, ver1.minor);
+ tt_int_op(4,==, ver1.micro);
+ tt_int_op(VER_RELEASE,==, ver1.status);
+ tt_int_op(999,==, ver1.patchlevel);
+ tt_int_op(0,==, tor_version_parse("0.1.2.4-alpha", &ver1));
+ tt_int_op(0,==, ver1.major);
+ tt_int_op(1,==, ver1.minor);
+ tt_int_op(2,==, ver1.micro);
+ tt_int_op(4,==, ver1.patchlevel);
+ tt_int_op(VER_RELEASE,==, ver1.status);
+ tt_str_op("alpha",==, ver1.status_tag);
+ tt_int_op(0,==, tor_version_parse("0.1.2.4", &ver1));
+ tt_int_op(0,==, ver1.major);
+ tt_int_op(1,==, ver1.minor);
+ tt_int_op(2,==, ver1.micro);
+ tt_int_op(4,==, ver1.patchlevel);
+ tt_int_op(VER_RELEASE,==, ver1.status);
+ tt_str_op("",==, ver1.status_tag);
#define tt_versionstatus_op(vs1, op, vs2) \
tt_assert_test_type(vs1,vs2,#vs1" "#op" "#vs2,version_status_t, \
@@ -368,53 +871,54 @@ test_dir_versions(void)
/* On list, not newer than any on same series. */
test_v_i_o(VS_UNRECOMMENDED,
"0.1.0.1", "Tor 0.1.0.2,Tor 0.0.9.5,Tor 0.1.1.0");
- test_eq(0, tor_version_as_new_as("Tor 0.0.5", "0.0.9pre1-cvs"));
- test_eq(1, tor_version_as_new_as(
+ tt_int_op(0,==, tor_version_as_new_as("Tor 0.0.5", "0.0.9pre1-cvs"));
+ tt_int_op(1,==, tor_version_as_new_as(
"Tor 0.0.8 on Darwin 64-121-192-100.c3-0."
"sfpo-ubr1.sfrn-sfpo.ca.cable.rcn.com Power Macintosh",
"0.0.8rc2"));
- test_eq(0, tor_version_as_new_as(
+ tt_int_op(0,==, tor_version_as_new_as(
"Tor 0.0.8 on Darwin 64-121-192-100.c3-0."
"sfpo-ubr1.sfrn-sfpo.ca.cable.rcn.com Power Macintosh", "0.0.8.2"));
/* Now try svn revisions. */
- test_eq(1, tor_version_as_new_as("Tor 0.2.1.0-dev (r100)",
+ tt_int_op(1,==, tor_version_as_new_as("Tor 0.2.1.0-dev (r100)",
"Tor 0.2.1.0-dev (r99)"));
- test_eq(1, tor_version_as_new_as("Tor 0.2.1.0-dev (r100) on Banana Jr",
+ tt_int_op(1,==, tor_version_as_new_as("Tor 0.2.1.0-dev (r100) on Banana Jr",
"Tor 0.2.1.0-dev (r99) on Hal 9000"));
- test_eq(1, tor_version_as_new_as("Tor 0.2.1.0-dev (r100)",
+ tt_int_op(1,==, tor_version_as_new_as("Tor 0.2.1.0-dev (r100)",
"Tor 0.2.1.0-dev on Colossus"));
- test_eq(0, tor_version_as_new_as("Tor 0.2.1.0-dev (r99)",
+ tt_int_op(0,==, tor_version_as_new_as("Tor 0.2.1.0-dev (r99)",
"Tor 0.2.1.0-dev (r100)"));
- test_eq(0, tor_version_as_new_as("Tor 0.2.1.0-dev (r99) on MCP",
+ tt_int_op(0,==, tor_version_as_new_as("Tor 0.2.1.0-dev (r99) on MCP",
"Tor 0.2.1.0-dev (r100) on AM"));
- test_eq(0, tor_version_as_new_as("Tor 0.2.1.0-dev",
+ tt_int_op(0,==, tor_version_as_new_as("Tor 0.2.1.0-dev",
"Tor 0.2.1.0-dev (r99)"));
- test_eq(1, tor_version_as_new_as("Tor 0.2.1.1",
+ tt_int_op(1,==, tor_version_as_new_as("Tor 0.2.1.1",
"Tor 0.2.1.0-dev (r99)"));
/* Now try git revisions */
- test_eq(0, tor_version_parse("0.5.6.7 (git-ff00ff)", &ver1));
- test_eq(0, ver1.major);
- test_eq(5, ver1.minor);
- test_eq(6, ver1.micro);
- test_eq(7, ver1.patchlevel);
- test_eq(3, ver1.git_tag_len);
- test_memeq(ver1.git_tag, "\xff\x00\xff", 3);
- test_eq(-1, tor_version_parse("0.5.6.7 (git-ff00xx)", &ver1));
- test_eq(-1, tor_version_parse("0.5.6.7 (git-ff00fff)", &ver1));
- test_eq(0, tor_version_parse("0.5.6.7 (git ff00fff)", &ver1));
+ tt_int_op(0,==, tor_version_parse("0.5.6.7 (git-ff00ff)", &ver1));
+ tt_int_op(0,==, ver1.major);
+ tt_int_op(5,==, ver1.minor);
+ tt_int_op(6,==, ver1.micro);
+ tt_int_op(7,==, ver1.patchlevel);
+ tt_int_op(3,==, ver1.git_tag_len);
+ tt_mem_op(ver1.git_tag,==, "\xff\x00\xff", 3);
+ tt_int_op(-1,==, tor_version_parse("0.5.6.7 (git-ff00xx)", &ver1));
+ tt_int_op(-1,==, tor_version_parse("0.5.6.7 (git-ff00fff)", &ver1));
+ tt_int_op(0,==, tor_version_parse("0.5.6.7 (git ff00fff)", &ver1));
done:
;
}
/** Run unit tests for directory fp_pair functions. */
static void
-test_dir_fp_pairs(void)
+test_dir_fp_pairs(void *arg)
{
smartlist_t *sl = smartlist_new();
fp_pair_t *pair;
+ (void)arg;
dir_split_resource_into_fingerprint_pairs(
/* Two pairs, out of order, with one duplicate. */
"73656372657420646174612E0000000000FFFFFF-"
@@ -424,13 +928,13 @@ test_dir_fp_pairs(void)
"48657861646563696d616c2069736e277420736f-"
"676f6f6420666f7220686964696e6720796f7572.z", sl);
- test_eq(smartlist_len(sl), 2);
+ tt_int_op(smartlist_len(sl),==, 2);
pair = smartlist_get(sl, 0);
- test_memeq(pair->first, "Hexadecimal isn't so", DIGEST_LEN);
- test_memeq(pair->second, "good for hiding your", DIGEST_LEN);
+ tt_mem_op(pair->first,==, "Hexadecimal isn't so", DIGEST_LEN);
+ tt_mem_op(pair->second,==, "good for hiding your", DIGEST_LEN);
pair = smartlist_get(sl, 1);
- test_memeq(pair->first, "secret data.\0\0\0\0\0\xff\xff\xff", DIGEST_LEN);
- test_memeq(pair->second, "Use AES-256 instead.", DIGEST_LEN);
+ tt_mem_op(pair->first,==, "secret data.\0\0\0\0\0\xff\xff\xff", DIGEST_LEN);
+ tt_mem_op(pair->second,==, "Use AES-256 instead.", DIGEST_LEN);
done:
SMARTLIST_FOREACH(sl, fp_pair_t *, pair, tor_free(pair));
@@ -557,7 +1061,7 @@ test_dir_split_fps(void *testdata)
}
static void
-test_dir_measured_bw_kb(void)
+test_dir_measured_bw_kb(void *arg)
{
measured_bw_line_t mbwl;
int i;
@@ -605,16 +1109,17 @@ test_dir_measured_bw_kb(void)
"end"
};
+ (void)arg;
for (i = 0; strcmp(lines_fail[i], "end"); i++) {
//fprintf(stderr, "Testing: %s\n", lines_fail[i]);
- test_assert(measured_bw_line_parse(&mbwl, lines_fail[i]) == -1);
+ tt_assert(measured_bw_line_parse(&mbwl, lines_fail[i]) == -1);
}
for (i = 0; strcmp(lines_pass[i], "end"); i++) {
//fprintf(stderr, "Testing: %s %d\n", lines_pass[i], TOR_ISSPACE('\n'));
- test_assert(measured_bw_line_parse(&mbwl, lines_pass[i]) == 0);
- test_assert(mbwl.bw_kb == 1024);
- test_assert(strcmp(mbwl.node_hex,
+ tt_assert(measured_bw_line_parse(&mbwl, lines_pass[i]) == 0);
+ tt_assert(mbwl.bw_kb == 1024);
+ tt_assert(strcmp(mbwl.node_hex,
"557365204145532d32353620696e73746561642e") == 0);
}
@@ -626,7 +1131,7 @@ test_dir_measured_bw_kb(void)
/** Do the measured bandwidth cache unit test */
static void
-test_dir_measured_bw_kb_cache(void)
+test_dir_measured_bw_kb_cache(void *arg)
{
/* Initial fake time_t for testing */
time_t curr = MBWC_INIT_TIME;
@@ -637,8 +1142,9 @@ test_dir_measured_bw_kb_cache(void)
time_t as_of;
/* First, clear the cache and assert that it's empty */
+ (void)arg;
dirserv_clear_measured_bw_cache();
- test_eq(dirserv_get_measured_bw_cache_size(), 0);
+ tt_int_op(dirserv_get_measured_bw_cache_size(),==, 0);
/*
* Set up test mbwls; none of the dirserv_cache_*() functions care about
* the node_hex field.
@@ -651,56 +1157,56 @@ test_dir_measured_bw_kb_cache(void)
mbwl[2].bw_kb = 80;
/* Try caching something */
dirserv_cache_measured_bw(&(mbwl[0]), curr);
- test_eq(dirserv_get_measured_bw_cache_size(), 1);
+ tt_int_op(dirserv_get_measured_bw_cache_size(),==, 1);
/* Okay, let's see if we can retrieve it */
- test_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,&bw, &as_of));
- test_eq(bw, 20);
- test_eq(as_of, MBWC_INIT_TIME);
+ tt_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,&bw, &as_of));
+ tt_int_op(bw,==, 20);
+ tt_int_op(as_of,==, MBWC_INIT_TIME);
/* Try retrieving it without some outputs */
- test_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,NULL, NULL));
- test_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,&bw, NULL));
- test_eq(bw, 20);
- test_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,NULL,&as_of));
- test_eq(as_of, MBWC_INIT_TIME);
+ tt_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,NULL, NULL));
+ tt_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,&bw, NULL));
+ tt_int_op(bw,==, 20);
+ tt_assert(dirserv_query_measured_bw_cache_kb(mbwl[0].node_id,NULL,&as_of));
+ tt_int_op(as_of,==, MBWC_INIT_TIME);
/* Now expire it */
curr += MAX_MEASUREMENT_AGE + 1;
dirserv_expire_measured_bw_cache(curr);
/* Check that the cache is empty */
- test_eq(dirserv_get_measured_bw_cache_size(), 0);
+ tt_int_op(dirserv_get_measured_bw_cache_size(),==, 0);
/* Check that we can't retrieve it */
- test_assert(!dirserv_query_measured_bw_cache_kb(mbwl[0].node_id, NULL,NULL));
+ tt_assert(!dirserv_query_measured_bw_cache_kb(mbwl[0].node_id, NULL,NULL));
/* Try caching a few things now */
dirserv_cache_measured_bw(&(mbwl[0]), curr);
- test_eq(dirserv_get_measured_bw_cache_size(), 1);
+ tt_int_op(dirserv_get_measured_bw_cache_size(),==, 1);
curr += MAX_MEASUREMENT_AGE / 4;
dirserv_cache_measured_bw(&(mbwl[1]), curr);
- test_eq(dirserv_get_measured_bw_cache_size(), 2);
+ tt_int_op(dirserv_get_measured_bw_cache_size(),==, 2);
curr += MAX_MEASUREMENT_AGE / 4;
dirserv_cache_measured_bw(&(mbwl[2]), curr);
- test_eq(dirserv_get_measured_bw_cache_size(), 3);
+ tt_int_op(dirserv_get_measured_bw_cache_size(),==, 3);
curr += MAX_MEASUREMENT_AGE / 4 + 1;
/* Do an expire that's too soon to get any of them */
dirserv_expire_measured_bw_cache(curr);
- test_eq(dirserv_get_measured_bw_cache_size(), 3);
+ tt_int_op(dirserv_get_measured_bw_cache_size(),==, 3);
/* Push the oldest one off the cliff */
curr += MAX_MEASUREMENT_AGE / 4;
dirserv_expire_measured_bw_cache(curr);
- test_eq(dirserv_get_measured_bw_cache_size(), 2);
+ tt_int_op(dirserv_get_measured_bw_cache_size(),==, 2);
/* And another... */
curr += MAX_MEASUREMENT_AGE / 4;
dirserv_expire_measured_bw_cache(curr);
- test_eq(dirserv_get_measured_bw_cache_size(), 1);
+ tt_int_op(dirserv_get_measured_bw_cache_size(),==, 1);
/* This should empty it out again */
curr += MAX_MEASUREMENT_AGE / 4;
dirserv_expire_measured_bw_cache(curr);
- test_eq(dirserv_get_measured_bw_cache_size(), 0);
+ tt_int_op(dirserv_get_measured_bw_cache_size(),==, 0);
done:
return;
}
static void
-test_dir_param_voting(void)
+test_dir_param_voting(void *arg)
{
networkstatus_t vote1, vote2, vote3, vote4;
smartlist_t *votes = smartlist_new();
@@ -709,6 +1215,7 @@ test_dir_param_voting(void)
/* dirvote_compute_params only looks at the net_params field of the votes,
so that's all we need to set.
*/
+ (void)arg;
memset(&vote1, 0, sizeof(vote1));
memset(&vote2, 0, sizeof(vote2));
memset(&vote3, 0, sizeof(vote3));
@@ -725,11 +1232,11 @@ test_dir_param_voting(void)
"abcd=20 c=60 cw=500 x-yz=-9 zzzzz=101", NULL, 0, 0);
smartlist_split_string(vote4.net_params,
"ab=900 abcd=200 c=1 cw=51 x-yz=100", NULL, 0, 0);
- test_eq(100, networkstatus_get_param(&vote4, "x-yz", 50, 0, 300));
- test_eq(222, networkstatus_get_param(&vote4, "foobar", 222, 0, 300));
- test_eq(80, networkstatus_get_param(&vote4, "ab", 12, 0, 80));
- test_eq(-8, networkstatus_get_param(&vote4, "ab", -12, -100, -8));
- test_eq(0, networkstatus_get_param(&vote4, "foobar", 0, -100, 8));
+ tt_int_op(100,==, networkstatus_get_param(&vote4, "x-yz", 50, 0, 300));
+ tt_int_op(222,==, networkstatus_get_param(&vote4, "foobar", 222, 0, 300));
+ tt_int_op(80,==, networkstatus_get_param(&vote4, "ab", 12, 0, 80));
+ tt_int_op(-8,==, networkstatus_get_param(&vote4, "ab", -12, -100, -8));
+ tt_int_op(0,==, networkstatus_get_param(&vote4, "foobar", 0, -100, 8));
smartlist_add(votes, &vote1);
@@ -737,59 +1244,59 @@ test_dir_param_voting(void)
* networks without many dirauths. */
res = dirvote_compute_params(votes, 12, 2);
- test_streq(res, "");
+ tt_str_op(res,==, "");
tor_free(res);
res = dirvote_compute_params(votes, 12, 1);
- test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-99");
+ tt_str_op(res,==, "ab=90 abcd=20 cw=50 x-yz=-99");
tor_free(res);
smartlist_add(votes, &vote2);
res = dirvote_compute_params(votes, 12, 2);
- test_streq(res, "ab=27 cw=5 x-yz=-99");
+ tt_str_op(res,==, "ab=27 cw=5 x-yz=-99");
tor_free(res);
res = dirvote_compute_params(votes, 12, 3);
- test_streq(res, "ab=27 cw=5 x-yz=-99");
+ tt_str_op(res,==, "ab=27 cw=5 x-yz=-99");
tor_free(res);
res = dirvote_compute_params(votes, 12, 6);
- test_streq(res, "");
+ tt_str_op(res,==, "");
tor_free(res);
smartlist_add(votes, &vote3);
res = dirvote_compute_params(votes, 12, 3);
- test_streq(res, "ab=27 abcd=20 cw=50 x-yz=-9");
+ tt_str_op(res,==, "ab=27 abcd=20 cw=50 x-yz=-9");
tor_free(res);
res = dirvote_compute_params(votes, 12, 5);
- test_streq(res, "cw=50 x-yz=-9");
+ tt_str_op(res,==, "cw=50 x-yz=-9");
tor_free(res);
res = dirvote_compute_params(votes, 12, 9);
- test_streq(res, "cw=50 x-yz=-9");
+ tt_str_op(res,==, "cw=50 x-yz=-9");
tor_free(res);
smartlist_add(votes, &vote4);
res = dirvote_compute_params(votes, 12, 4);
- test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9");
+ tt_str_op(res,==, "ab=90 abcd=20 cw=50 x-yz=-9");
tor_free(res);
res = dirvote_compute_params(votes, 12, 5);
- test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9");
+ tt_str_op(res,==, "ab=90 abcd=20 cw=50 x-yz=-9");
tor_free(res);
/* Test that the special-cased "at least three dirauths voted for
* this param" logic works as expected. */
res = dirvote_compute_params(votes, 12, 6);
- test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9");
+ tt_str_op(res,==, "ab=90 abcd=20 cw=50 x-yz=-9");
tor_free(res);
res = dirvote_compute_params(votes, 12, 10);
- test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9");
+ tt_str_op(res,==, "ab=90 abcd=20 cw=50 x-yz=-9");
tor_free(res);
done:
@@ -821,14 +1328,14 @@ static void
test_same_voter(networkstatus_voter_info_t *v1,
networkstatus_voter_info_t *v2)
{
- test_streq(v1->nickname, v2->nickname);
- test_memeq(v1->identity_digest, v2->identity_digest, DIGEST_LEN);
- test_streq(v1->address, v2->address);
- test_eq(v1->addr, v2->addr);
- test_eq(v1->dir_port, v2->dir_port);
- test_eq(v1->or_port, v2->or_port);
- test_streq(v1->contact, v2->contact);
- test_memeq(v1->vote_digest, v2->vote_digest, DIGEST_LEN);
+ tt_str_op(v1->nickname,==, v2->nickname);
+ tt_mem_op(v1->identity_digest,==, v2->identity_digest, DIGEST_LEN);
+ tt_str_op(v1->address,==, v2->address);
+ tt_int_op(v1->addr,==, v2->addr);
+ tt_int_op(v1->dir_port,==, v2->dir_port);
+ tt_int_op(v1->or_port,==, v2->or_port);
+ tt_str_op(v1->contact,==, v2->contact);
+ tt_mem_op(v1->vote_digest,==, v2->vote_digest, DIGEST_LEN);
done:
;
}
@@ -965,7 +1472,7 @@ gen_routerstatus_for_v3ns(int idx, time_t now)
break;
default:
/* Shouldn't happen */
- test_assert(0);
+ tt_assert(0);
}
if (vrs) {
vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
@@ -986,14 +1493,14 @@ vote_tweaks_for_v3ns(networkstatus_t *v, int voter, time_t now)
vote_routerstatus_t *vrs;
const char *msg = NULL;
- test_assert(v);
+ tt_assert(v);
(void)now;
if (voter == 1) {
measured_bw_line_t mbw;
memset(mbw.node_id, 33, sizeof(mbw.node_id));
mbw.bw_kb = 1024;
- test_assert(measured_bw_line_apply(&mbw,
+ tt_assert(measured_bw_line_apply(&mbw,
v->routerstatus_list) == 1);
} else if (voter == 2 || voter == 3) {
/* Monkey around with the list a bit */
@@ -1009,7 +1516,7 @@ vote_tweaks_for_v3ns(networkstatus_t *v, int voter, time_t now)
vote_routerstatus_free(vrs);
vrs = smartlist_get(v->routerstatus_list, 0);
memset(vrs->status.descriptor_digest, (int)'Z', DIGEST_LEN);
- test_assert(router_add_to_routerlist(
+ tt_assert(router_add_to_routerlist(
generate_ri_from_rs(vrs), &msg,0,0) >= 0);
}
}
@@ -1027,9 +1534,9 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now)
routerstatus_t *rs;
tor_addr_t addr_ipv6;
- test_assert(vrs);
+ tt_assert(vrs);
rs = &(vrs->status);
- test_assert(rs);
+ tt_assert(rs);
/* Split out by digests to test */
if (tor_memeq(rs->identity_digest,
@@ -1038,17 +1545,17 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now)
DIGEST_LEN) &&
(voter == 1)) {
/* Check the first routerstatus. */
- test_streq(vrs->version, "0.1.2.14");
- test_eq(rs->published_on, now-1500);
- test_streq(rs->nickname, "router2");
- test_memeq(rs->identity_digest,
+ tt_str_op(vrs->version,==, "0.1.2.14");
+ tt_int_op(rs->published_on,==, now-1500);
+ tt_str_op(rs->nickname,==, "router2");
+ tt_mem_op(rs->identity_digest,==,
"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"
"\x3\x3\x3\x3",
DIGEST_LEN);
- test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN);
- test_eq(rs->addr, 0x99008801);
- test_eq(rs->or_port, 443);
- test_eq(rs->dir_port, 8000);
+ tt_mem_op(rs->descriptor_digest,==, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN);
+ tt_int_op(rs->addr,==, 0x99008801);
+ tt_int_op(rs->or_port,==, 443);
+ tt_int_op(rs->dir_port,==, 8000);
/* no flags except "running" (16) and "v2dir" (64) */
tt_u64_op(vrs->flags, ==, U64_LITERAL(80));
} else if (tor_memeq(rs->identity_digest,
@@ -1056,24 +1563,24 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now)
"\x5\x5\x5\x5",
DIGEST_LEN) &&
(voter == 1 || voter == 2)) {
- test_memeq(rs->identity_digest,
+ tt_mem_op(rs->identity_digest,==,
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5"
"\x5\x5\x5\x5",
DIGEST_LEN);
if (voter == 1) {
/* Check the second routerstatus. */
- test_streq(vrs->version, "0.2.0.5");
- test_eq(rs->published_on, now-1000);
- test_streq(rs->nickname, "router1");
+ tt_str_op(vrs->version,==, "0.2.0.5");
+ tt_int_op(rs->published_on,==, now-1000);
+ tt_str_op(rs->nickname,==, "router1");
}
- test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
- test_eq(rs->addr, 0x99009901);
- test_eq(rs->or_port, 443);
- test_eq(rs->dir_port, 0);
+ tt_mem_op(rs->descriptor_digest,==, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
+ tt_int_op(rs->addr,==, 0x99009901);
+ tt_int_op(rs->or_port,==, 443);
+ tt_int_op(rs->dir_port,==, 0);
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
- test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
- test_eq(rs->ipv6_orport, 4711);
+ tt_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
+ tt_int_op(rs->ipv6_orport,==, 4711);
if (voter == 1) {
/* all except "authority" (1) and "v2dir" (64) */
tt_u64_op(vrs->flags, ==, U64_LITERAL(190));
@@ -1087,14 +1594,14 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now)
DIGEST_LEN) &&
(voter == 1 || voter == 2)) {
/* Check the measured bandwidth bits */
- test_assert(vrs->has_measured_bw &&
+ tt_assert(vrs->has_measured_bw &&
vrs->measured_bw_kb == 1024);
} else {
/*
* Didn't expect this, but the old unit test only checked some of them,
* so don't assert.
*/
- /* test_assert(0); */
+ /* tt_assert(0); */
}
done:
@@ -1109,9 +1616,9 @@ test_consensus_for_v3ns(networkstatus_t *con, time_t now)
{
(void)now;
- test_assert(con);
- test_assert(!con->cert);
- test_eq(2, smartlist_len(con->routerstatus_list));
+ tt_assert(con);
+ tt_assert(!con->cert);
+ tt_int_op(2,==, smartlist_len(con->routerstatus_list));
/* There should be two listed routers: one with identity 3, one with
* identity 5. */
@@ -1127,7 +1634,7 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now)
{
tor_addr_t addr_ipv6;
- test_assert(rs);
+ tt_assert(rs);
/* There should be two listed routers: one with identity 3, one with
* identity 5. */
@@ -1136,49 +1643,49 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now)
"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"
"\x3\x3",
DIGEST_LEN)) {
- test_memeq(rs->identity_digest,
+ tt_mem_op(rs->identity_digest,==,
"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3",
DIGEST_LEN);
- test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN);
- test_assert(!rs->is_authority);
- test_assert(!rs->is_exit);
- test_assert(!rs->is_fast);
- test_assert(!rs->is_possible_guard);
- test_assert(!rs->is_stable);
+ tt_mem_op(rs->descriptor_digest,==, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN);
+ tt_assert(!rs->is_authority);
+ tt_assert(!rs->is_exit);
+ tt_assert(!rs->is_fast);
+ tt_assert(!rs->is_possible_guard);
+ tt_assert(!rs->is_stable);
/* (If it wasn't running it wouldn't be here) */
- test_assert(rs->is_flagged_running);
- test_assert(!rs->is_valid);
- test_assert(!rs->is_named);
+ tt_assert(rs->is_flagged_running);
+ tt_assert(!rs->is_valid);
+ tt_assert(!rs->is_named);
/* XXXX check version */
} else if (tor_memeq(rs->identity_digest,
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5"
"\x5\x5\x5\x5",
DIGEST_LEN)) {
/* This one showed up in 3 digests. Twice with ID 'M', once with 'Z'. */
- test_memeq(rs->identity_digest,
+ tt_mem_op(rs->identity_digest,==,
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5",
DIGEST_LEN);
- test_streq(rs->nickname, "router1");
- test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
- test_eq(rs->published_on, now-1000);
- test_eq(rs->addr, 0x99009901);
- test_eq(rs->or_port, 443);
- test_eq(rs->dir_port, 0);
+ tt_str_op(rs->nickname,==, "router1");
+ tt_mem_op(rs->descriptor_digest,==, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
+ tt_int_op(rs->published_on,==, now-1000);
+ tt_int_op(rs->addr,==, 0x99009901);
+ tt_int_op(rs->or_port,==, 443);
+ tt_int_op(rs->dir_port,==, 0);
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
- test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
- test_eq(rs->ipv6_orport, 4711);
- test_assert(!rs->is_authority);
- test_assert(rs->is_exit);
- test_assert(rs->is_fast);
- test_assert(rs->is_possible_guard);
- test_assert(rs->is_stable);
- test_assert(rs->is_flagged_running);
- test_assert(rs->is_valid);
- test_assert(!rs->is_named);
+ tt_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
+ tt_int_op(rs->ipv6_orport,==, 4711);
+ tt_assert(!rs->is_authority);
+ tt_assert(rs->is_exit);
+ tt_assert(rs->is_fast);
+ tt_assert(rs->is_possible_guard);
+ tt_assert(rs->is_stable);
+ tt_assert(rs->is_flagged_running);
+ tt_assert(rs->is_valid);
+ tt_assert(!rs->is_named);
/* XXXX check version */
} else {
/* Weren't expecting this... */
- test_assert(0);
+ tt_assert(0);
}
done:
@@ -1226,31 +1733,31 @@ test_a_networkstatus(
networkstatus_t *con2=NULL, *con_md2=NULL, *con3=NULL, *con_md3=NULL;
ns_detached_signatures_t *dsig1=NULL, *dsig2=NULL;
- test_assert(vrs_gen);
- test_assert(rs_test);
- test_assert(vrs_test);
+ tt_assert(vrs_gen);
+ tt_assert(rs_test);
+ tt_assert(vrs_test);
/* Parse certificates and keys. */
cert1 = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL);
- test_assert(cert1);
+ tt_assert(cert1);
cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL);
- test_assert(cert2);
+ tt_assert(cert2);
cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3, NULL);
- test_assert(cert3);
+ tt_assert(cert3);
sign_skey_1 = crypto_pk_new();
sign_skey_2 = crypto_pk_new();
sign_skey_3 = crypto_pk_new();
sign_skey_leg1 = pk_generate(4);
- test_assert(!crypto_pk_read_private_key_from_string(sign_skey_1,
+ tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_1,
AUTHORITY_SIGNKEY_1, -1));
- test_assert(!crypto_pk_read_private_key_from_string(sign_skey_2,
+ tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_2,
AUTHORITY_SIGNKEY_2, -1));
- test_assert(!crypto_pk_read_private_key_from_string(sign_skey_3,
+ tt_assert(!crypto_pk_read_private_key_from_string(sign_skey_3,
AUTHORITY_SIGNKEY_3, -1));
- test_assert(!crypto_pk_cmp_keys(sign_skey_1, cert1->signing_key));
- test_assert(!crypto_pk_cmp_keys(sign_skey_2, cert2->signing_key));
+ tt_assert(!crypto_pk_cmp_keys(sign_skey_1, cert1->signing_key));
+ tt_assert(!crypto_pk_cmp_keys(sign_skey_2, cert2->signing_key));
/*
* Set up a vote; generate it; try to parse it.
@@ -1292,7 +1799,7 @@ test_a_networkstatus(
vrs = vrs_gen(idx, now);
if (vrs) {
smartlist_add(vote->routerstatus_list, vrs);
- test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs),
+ tt_assert(router_add_to_routerlist(generate_ri_from_rs(vrs),
&msg,0,0)>=0);
++idx;
}
@@ -1301,41 +1808,41 @@ test_a_networkstatus(
/* dump the vote and try to parse it. */
v1_text = format_networkstatus_vote(sign_skey_1, vote);
- test_assert(v1_text);
+ tt_assert(v1_text);
v1 = networkstatus_parse_vote_from_string(v1_text, NULL, NS_TYPE_VOTE);
- test_assert(v1);
+ tt_assert(v1);
/* Make sure the parsed thing was right. */
- test_eq(v1->type, NS_TYPE_VOTE);
- test_eq(v1->published, vote->published);
- test_eq(v1->valid_after, vote->valid_after);
- test_eq(v1->fresh_until, vote->fresh_until);
- test_eq(v1->valid_until, vote->valid_until);
- test_eq(v1->vote_seconds, vote->vote_seconds);
- test_eq(v1->dist_seconds, vote->dist_seconds);
- test_streq(v1->client_versions, vote->client_versions);
- test_streq(v1->server_versions, vote->server_versions);
- test_assert(v1->voters && smartlist_len(v1->voters));
+ tt_int_op(v1->type,==, NS_TYPE_VOTE);
+ tt_int_op(v1->published,==, vote->published);
+ tt_int_op(v1->valid_after,==, vote->valid_after);
+ tt_int_op(v1->fresh_until,==, vote->fresh_until);
+ tt_int_op(v1->valid_until,==, vote->valid_until);
+ tt_int_op(v1->vote_seconds,==, vote->vote_seconds);
+ tt_int_op(v1->dist_seconds,==, vote->dist_seconds);
+ tt_str_op(v1->client_versions,==, vote->client_versions);
+ tt_str_op(v1->server_versions,==, vote->server_versions);
+ tt_assert(v1->voters && smartlist_len(v1->voters));
voter = smartlist_get(v1->voters, 0);
- test_streq(voter->nickname, "Voter1");
- test_streq(voter->address, "1.2.3.4");
- test_eq(voter->addr, 0x01020304);
- test_eq(voter->dir_port, 80);
- test_eq(voter->or_port, 9000);
- test_streq(voter->contact, "voter@example.com");
- test_assert(v1->cert);
- test_assert(!crypto_pk_cmp_keys(sign_skey_1, v1->cert->signing_key));
+ tt_str_op(voter->nickname,==, "Voter1");
+ tt_str_op(voter->address,==, "1.2.3.4");
+ tt_int_op(voter->addr,==, 0x01020304);
+ tt_int_op(voter->dir_port,==, 80);
+ tt_int_op(voter->or_port,==, 9000);
+ tt_str_op(voter->contact,==, "voter@example.com");
+ tt_assert(v1->cert);
+ tt_assert(!crypto_pk_cmp_keys(sign_skey_1, v1->cert->signing_key));
cp = smartlist_join_strings(v1->known_flags, ":", 0, NULL);
- test_streq(cp, "Authority:Exit:Fast:Guard:Running:Stable:V2Dir:Valid");
+ tt_str_op(cp,==, "Authority:Exit:Fast:Guard:Running:Stable:V2Dir:Valid");
tor_free(cp);
- test_eq(smartlist_len(v1->routerstatus_list), n_vrs);
+ tt_int_op(smartlist_len(v1->routerstatus_list),==, n_vrs);
if (vote_tweaks) params_tweaked += vote_tweaks(v1, 1, now);
/* Check the routerstatuses. */
for (idx = 0; idx < n_vrs; ++idx) {
vrs = smartlist_get(v1->routerstatus_list, idx);
- test_assert(vrs);
+ tt_assert(vrs);
vrs_test(vrs, 1, now);
}
@@ -1365,15 +1872,15 @@ test_a_networkstatus(
/* generate and parse v2. */
v2_text = format_networkstatus_vote(sign_skey_2, vote);
- test_assert(v2_text);
+ tt_assert(v2_text);
v2 = networkstatus_parse_vote_from_string(v2_text, NULL, NS_TYPE_VOTE);
- test_assert(v2);
+ tt_assert(v2);
if (vote_tweaks) params_tweaked += vote_tweaks(v2, 2, now);
/* Check that flags come out right.*/
cp = smartlist_join_strings(v2->known_flags, ":", 0, NULL);
- test_streq(cp, "Authority:Exit:Fast:Guard:MadeOfCheese:MadeOfTin:"
+ tt_str_op(cp,==, "Authority:Exit:Fast:Guard:MadeOfCheese:MadeOfTin:"
"Running:Stable:V2Dir:Valid");
tor_free(cp);
@@ -1381,7 +1888,7 @@ test_a_networkstatus(
n_vrs = smartlist_len(v2->routerstatus_list);
for (idx = 0; idx < n_vrs; ++idx) {
vrs = smartlist_get(v2->routerstatus_list, idx);
- test_assert(vrs);
+ tt_assert(vrs);
vrs_test(vrs, 2, now);
}
@@ -1409,10 +1916,10 @@ test_a_networkstatus(
memset(voter->legacy_id_digest, (int)'A', DIGEST_LEN);
v3_text = format_networkstatus_vote(sign_skey_3, vote);
- test_assert(v3_text);
+ tt_assert(v3_text);
v3 = networkstatus_parse_vote_from_string(v3_text, NULL, NS_TYPE_VOTE);
- test_assert(v3);
+ tt_assert(v3);
if (vote_tweaks) params_tweaked += vote_tweaks(v3, 3, now);
@@ -1426,10 +1933,10 @@ test_a_networkstatus(
"AAAAAAAAAAAAAAAAAAAA",
sign_skey_leg1,
FLAV_NS);
- test_assert(consensus_text);
+ tt_assert(consensus_text);
con = networkstatus_parse_vote_from_string(consensus_text, NULL,
NS_TYPE_CONSENSUS);
- test_assert(con);
+ tt_assert(con);
//log_notice(LD_GENERAL, "<<%s>>\n<<%s>>\n<<%s>>\n",
// v1_text, v2_text, v3_text);
consensus_text_md = networkstatus_compute_consensus(votes, 3,
@@ -1438,38 +1945,38 @@ test_a_networkstatus(
"AAAAAAAAAAAAAAAAAAAA",
sign_skey_leg1,
FLAV_MICRODESC);
- test_assert(consensus_text_md);
+ tt_assert(consensus_text_md);
con_md = networkstatus_parse_vote_from_string(consensus_text_md, NULL,
NS_TYPE_CONSENSUS);
- test_assert(con_md);
- test_eq(con_md->flavor, FLAV_MICRODESC);
+ tt_assert(con_md);
+ tt_int_op(con_md->flavor,==, FLAV_MICRODESC);
/* Check consensus contents. */
- test_assert(con->type == NS_TYPE_CONSENSUS);
- test_eq(con->published, 0); /* this field only appears in votes. */
- test_eq(con->valid_after, now+1000);
- test_eq(con->fresh_until, now+2003); /* median */
- test_eq(con->valid_until, now+3000);
- test_eq(con->vote_seconds, 100);
- test_eq(con->dist_seconds, 250); /* median */
- test_streq(con->client_versions, "0.1.2.14");
- test_streq(con->server_versions, "0.1.2.15,0.1.2.16");
+ tt_assert(con->type == NS_TYPE_CONSENSUS);
+ tt_int_op(con->published,==, 0); /* this field only appears in votes. */
+ tt_int_op(con->valid_after,==, now+1000);
+ tt_int_op(con->fresh_until,==, now+2003); /* median */
+ tt_int_op(con->valid_until,==, now+3000);
+ tt_int_op(con->vote_seconds,==, 100);
+ tt_int_op(con->dist_seconds,==, 250); /* median */
+ tt_str_op(con->client_versions,==, "0.1.2.14");
+ tt_str_op(con->server_versions,==, "0.1.2.15,0.1.2.16");
cp = smartlist_join_strings(v2->known_flags, ":", 0, NULL);
- test_streq(cp, "Authority:Exit:Fast:Guard:MadeOfCheese:MadeOfTin:"
+ tt_str_op(cp,==, "Authority:Exit:Fast:Guard:MadeOfCheese:MadeOfTin:"
"Running:Stable:V2Dir:Valid");
tor_free(cp);
if (!params_tweaked) {
/* Skip this one if vote_tweaks() messed with the param lists */
cp = smartlist_join_strings(con->net_params, ":", 0, NULL);
- test_streq(cp, "circuitwindow=80:foo=660");
+ tt_str_op(cp,==, "circuitwindow=80:foo=660");
tor_free(cp);
}
- test_eq(4, smartlist_len(con->voters)); /*3 voters, 1 legacy key.*/
+ tt_int_op(4,==, smartlist_len(con->voters)); /*3 voters, 1 legacy key.*/
/* The voter id digests should be in this order. */
- test_assert(memcmp(cert2->cache_info.identity_digest,
+ tt_assert(memcmp(cert2->cache_info.identity_digest,
cert1->cache_info.identity_digest,DIGEST_LEN)<0);
- test_assert(memcmp(cert1->cache_info.identity_digest,
+ tt_assert(memcmp(cert1->cache_info.identity_digest,
cert3->cache_info.identity_digest,DIGEST_LEN)<0);
test_same_voter(smartlist_get(con->voters, 1),
smartlist_get(v2->voters, 0));
@@ -1484,26 +1991,26 @@ test_a_networkstatus(
n_rs = smartlist_len(con->routerstatus_list);
for (idx = 0; idx < n_rs; ++idx) {
rs = smartlist_get(con->routerstatus_list, idx);
- test_assert(rs);
+ tt_assert(rs);
rs_test(rs, now);
}
/* Check signatures. the first voter is a pseudo-entry with a legacy key.
* The second one hasn't signed. The fourth one has signed: validate it. */
voter = smartlist_get(con->voters, 1);
- test_eq(smartlist_len(voter->sigs), 0);
+ tt_int_op(smartlist_len(voter->sigs),==, 0);
voter = smartlist_get(con->voters, 3);
- test_eq(smartlist_len(voter->sigs), 1);
+ tt_int_op(smartlist_len(voter->sigs),==, 1);
sig = smartlist_get(voter->sigs, 0);
- test_assert(sig->signature);
- test_assert(!sig->good_signature);
- test_assert(!sig->bad_signature);
+ tt_assert(sig->signature);
+ tt_assert(!sig->good_signature);
+ tt_assert(!sig->bad_signature);
- test_assert(!networkstatus_check_document_signature(con, sig, cert3));
- test_assert(sig->signature);
- test_assert(sig->good_signature);
- test_assert(!sig->bad_signature);
+ tt_assert(!networkstatus_check_document_signature(con, sig, cert3));
+ tt_assert(sig->signature);
+ tt_assert(sig->good_signature);
+ tt_assert(!sig->bad_signature);
{
const char *msg=NULL;
@@ -1526,10 +2033,10 @@ test_a_networkstatus(
cert1->identity_key,
sign_skey_1, NULL,NULL,
FLAV_MICRODESC);
- test_assert(consensus_text2);
- test_assert(consensus_text3);
- test_assert(consensus_text_md2);
- test_assert(consensus_text_md3);
+ tt_assert(consensus_text2);
+ tt_assert(consensus_text3);
+ tt_assert(consensus_text_md2);
+ tt_assert(consensus_text_md3);
con2 = networkstatus_parse_vote_from_string(consensus_text2, NULL,
NS_TYPE_CONSENSUS);
con3 = networkstatus_parse_vote_from_string(consensus_text3, NULL,
@@ -1538,17 +2045,17 @@ test_a_networkstatus(
NS_TYPE_CONSENSUS);
con_md3 = networkstatus_parse_vote_from_string(consensus_text_md3, NULL,
NS_TYPE_CONSENSUS);
- test_assert(con2);
- test_assert(con3);
- test_assert(con_md2);
- test_assert(con_md3);
+ tt_assert(con2);
+ tt_assert(con3);
+ tt_assert(con_md2);
+ tt_assert(con_md3);
/* All three should have the same digest. */
- test_memeq(&con->digests, &con2->digests, sizeof(digests_t));
- test_memeq(&con->digests, &con3->digests, sizeof(digests_t));
+ tt_mem_op(&con->digests,==, &con2->digests, sizeof(digests_t));
+ tt_mem_op(&con->digests,==, &con3->digests, sizeof(digests_t));
- test_memeq(&con_md->digests, &con_md2->digests, sizeof(digests_t));
- test_memeq(&con_md->digests, &con_md3->digests, sizeof(digests_t));
+ tt_mem_op(&con_md->digests,==, &con_md2->digests, sizeof(digests_t));
+ tt_mem_op(&con_md->digests,==, &con_md3->digests, sizeof(digests_t));
/* Extract a detached signature from con3. */
detached_text1 = get_detached_sigs(con3, con_md3);
@@ -1558,50 +2065,51 @@ test_a_networkstatus(
tt_assert(dsig1);
/* Are parsed values as expected? */
- test_eq(dsig1->valid_after, con3->valid_after);
- test_eq(dsig1->fresh_until, con3->fresh_until);
- test_eq(dsig1->valid_until, con3->valid_until);
+ tt_int_op(dsig1->valid_after,==, con3->valid_after);
+ tt_int_op(dsig1->fresh_until,==, con3->fresh_until);
+ tt_int_op(dsig1->valid_until,==, con3->valid_until);
{
digests_t *dsig_digests = strmap_get(dsig1->digests, "ns");
- test_assert(dsig_digests);
- test_memeq(dsig_digests->d[DIGEST_SHA1], con3->digests.d[DIGEST_SHA1],
+ tt_assert(dsig_digests);
+ tt_mem_op(dsig_digests->d[DIGEST_SHA1],==, con3->digests.d[DIGEST_SHA1],
DIGEST_LEN);
dsig_digests = strmap_get(dsig1->digests, "microdesc");
- test_assert(dsig_digests);
- test_memeq(dsig_digests->d[DIGEST_SHA256],
+ tt_assert(dsig_digests);
+ tt_mem_op(dsig_digests->d[DIGEST_SHA256],==,
con_md3->digests.d[DIGEST_SHA256],
DIGEST256_LEN);
}
{
smartlist_t *dsig_signatures = strmap_get(dsig1->signatures, "ns");
- test_assert(dsig_signatures);
- test_eq(1, smartlist_len(dsig_signatures));
+ tt_assert(dsig_signatures);
+ tt_int_op(1,==, smartlist_len(dsig_signatures));
sig = smartlist_get(dsig_signatures, 0);
- test_memeq(sig->identity_digest, cert1->cache_info.identity_digest,
+ tt_mem_op(sig->identity_digest,==, cert1->cache_info.identity_digest,
DIGEST_LEN);
- test_eq(sig->alg, DIGEST_SHA1);
+ tt_int_op(sig->alg,==, DIGEST_SHA1);
dsig_signatures = strmap_get(dsig1->signatures, "microdesc");
- test_assert(dsig_signatures);
- test_eq(1, smartlist_len(dsig_signatures));
+ tt_assert(dsig_signatures);
+ tt_int_op(1,==, smartlist_len(dsig_signatures));
sig = smartlist_get(dsig_signatures, 0);
- test_memeq(sig->identity_digest, cert1->cache_info.identity_digest,
+ tt_mem_op(sig->identity_digest,==, cert1->cache_info.identity_digest,
DIGEST_LEN);
- test_eq(sig->alg, DIGEST_SHA256);
+ tt_int_op(sig->alg,==, DIGEST_SHA256);
}
/* Try adding it to con2. */
detached_text2 = get_detached_sigs(con2,con_md2);
- test_eq(1, networkstatus_add_detached_signatures(con2, dsig1, "test",
+ tt_int_op(1,==, networkstatus_add_detached_signatures(con2, dsig1, "test",
LOG_INFO, &msg));
tor_free(detached_text2);
- test_eq(1, networkstatus_add_detached_signatures(con_md2, dsig1, "test",
+ tt_int_op(1,==,
+ networkstatus_add_detached_signatures(con_md2, dsig1, "test",
LOG_INFO, &msg));
tor_free(detached_text2);
detached_text2 = get_detached_sigs(con2,con_md2);
//printf("\n<%s>\n", detached_text2);
dsig2 = networkstatus_parse_detached_signatures(detached_text2, NULL);
- test_assert(dsig2);
+ tt_assert(dsig2);
/*
printf("\n");
SMARTLIST_FOREACH(dsig2->signatures, networkstatus_voter_info_t *, vi, {
@@ -1610,28 +2118,28 @@ test_a_networkstatus(
printf("%s\n", hd);
});
*/
- test_eq(2,
+ tt_int_op(2,==,
smartlist_len((smartlist_t*)strmap_get(dsig2->signatures, "ns")));
- test_eq(2,
+ tt_int_op(2,==,
smartlist_len((smartlist_t*)strmap_get(dsig2->signatures,
"microdesc")));
/* Try adding to con2 twice; verify that nothing changes. */
- test_eq(0, networkstatus_add_detached_signatures(con2, dsig1, "test",
+ tt_int_op(0,==, networkstatus_add_detached_signatures(con2, dsig1, "test",
LOG_INFO, &msg));
/* Add to con. */
- test_eq(2, networkstatus_add_detached_signatures(con, dsig2, "test",
+ tt_int_op(2,==, networkstatus_add_detached_signatures(con, dsig2, "test",
LOG_INFO, &msg));
/* Check signatures */
voter = smartlist_get(con->voters, 1);
sig = smartlist_get(voter->sigs, 0);
- test_assert(sig);
- test_assert(!networkstatus_check_document_signature(con, sig, cert2));
+ tt_assert(sig);
+ tt_assert(!networkstatus_check_document_signature(con, sig, cert2));
voter = smartlist_get(con->voters, 2);
sig = smartlist_get(voter->sigs, 0);
- test_assert(sig);
- test_assert(!networkstatus_check_document_signature(con, sig, cert1));
+ tt_assert(sig);
+ tt_assert(!networkstatus_check_document_signature(con, sig, cert1));
}
done:
@@ -1693,8 +2201,9 @@ test_a_networkstatus(
/** Run unit tests for generating and parsing V3 consensus networkstatus
* documents. */
static void
-test_dir_v3_networkstatus(void)
+test_dir_v3_networkstatus(void *arg)
{
+ (void)arg;
test_a_networkstatus(gen_routerstatus_for_v3ns,
vote_tweaks_for_v3ns,
test_vrs_for_v3ns,
@@ -1733,10 +2242,37 @@ test_dir_scale_bw(void *testdata)
tt_assert(total <= (U64_LITERAL(1)<<62));
for (i=0; i<8; ++i) {
+ /* vals[2].u64 is the scaled value of 1.0 */
double ratio = ((double)vals[i].u64) / vals[2].u64;
tt_double_op(fabs(ratio - v[i]), <, .00001);
}
+ /* test handling of no entries */
+ total = 1;
+ scale_array_elements_to_u64(vals, 0, &total);
+ tt_assert(total == 0);
+
+ /* make sure we don't read the array when we have no entries
+ * may require compiler flags to catch NULL dereferences */
+ total = 1;
+ scale_array_elements_to_u64(NULL, 0, &total);
+ tt_assert(total == 0);
+
+ scale_array_elements_to_u64(NULL, 0, NULL);
+
+ /* test handling of zero totals */
+ total = 1;
+ vals[0].dbl = 0.0;
+ scale_array_elements_to_u64(vals, 1, &total);
+ tt_assert(total == 0);
+ tt_assert(vals[0].u64 == 0);
+
+ vals[0].dbl = 0.0;
+ vals[1].dbl = 0.0;
+ scale_array_elements_to_u64(vals, 2, NULL);
+ tt_assert(vals[0].u64 == 0);
+ tt_assert(vals[1].u64 == 0);
+
done:
;
}
@@ -1942,7 +2478,7 @@ gen_routerstatus_for_umbw(int idx, time_t now)
break;
default:
/* Shouldn't happen */
- test_assert(0);
+ tt_assert(0);
}
if (vrs) {
vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
@@ -1964,11 +2500,11 @@ vote_tweaks_for_umbw(networkstatus_t *v, int voter, time_t now)
char *maxbw_param = NULL;
int rv = 0;
- test_assert(v);
+ tt_assert(v);
(void)voter;
(void)now;
- test_assert(v->supported_methods);
+ 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 */
@@ -1978,7 +2514,7 @@ vote_tweaks_for_umbw(networkstatus_t *v, int voter, time_t now)
/* If we're using a non-default clip bandwidth, add it to net_params */
if (alternate_clip_bw > 0) {
tor_asprintf(&maxbw_param, "maxunmeasuredbw=%u", alternate_clip_bw);
- test_assert(maxbw_param);
+ tt_assert(maxbw_param);
if (maxbw_param) {
smartlist_add(v->net_params, maxbw_param);
rv = 1;
@@ -2001,9 +2537,9 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now)
alternate_clip_bw : DEFAULT_MAX_UNMEASURED_BW_KB;
(void)voter;
- test_assert(vrs);
+ tt_assert(vrs);
rs = &(vrs->status);
- test_assert(rs);
+ tt_assert(rs);
/* Split out by digests to test */
if (tor_memeq(rs->identity_digest,
@@ -2014,21 +2550,21 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now)
* Check the first routerstatus - measured bandwidth below the clip
* cutoff.
*/
- test_streq(vrs->version, "0.1.2.14");
- test_eq(rs->published_on, now-1500);
- test_streq(rs->nickname, "router2");
- test_memeq(rs->identity_digest,
+ tt_str_op(vrs->version,==, "0.1.2.14");
+ tt_int_op(rs->published_on,==, now-1500);
+ tt_str_op(rs->nickname,==, "router2");
+ tt_mem_op(rs->identity_digest,==,
"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"
"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3",
DIGEST_LEN);
- test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN);
- test_eq(rs->addr, 0x99008801);
- test_eq(rs->or_port, 443);
- test_eq(rs->dir_port, 8000);
- test_assert(rs->has_bandwidth);
- test_assert(vrs->has_measured_bw);
- test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb / 2);
- test_eq(vrs->measured_bw_kb, max_unmeasured_bw_kb / 2);
+ tt_mem_op(rs->descriptor_digest,==, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN);
+ tt_int_op(rs->addr,==, 0x99008801);
+ tt_int_op(rs->or_port,==, 443);
+ tt_int_op(rs->dir_port,==, 8000);
+ tt_assert(rs->has_bandwidth);
+ tt_assert(vrs->has_measured_bw);
+ tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb / 2);
+ tt_int_op(vrs->measured_bw_kb,==, max_unmeasured_bw_kb / 2);
} else if (tor_memeq(rs->identity_digest,
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5"
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5",
@@ -2038,24 +2574,24 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now)
* Check the second routerstatus - measured bandwidth above the clip
* cutoff.
*/
- test_streq(vrs->version, "0.2.0.5");
- test_eq(rs->published_on, now-1000);
- test_streq(rs->nickname, "router1");
- test_memeq(rs->identity_digest,
+ tt_str_op(vrs->version,==, "0.2.0.5");
+ tt_int_op(rs->published_on,==, now-1000);
+ tt_str_op(rs->nickname,==, "router1");
+ tt_mem_op(rs->identity_digest,==,
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5"
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5",
DIGEST_LEN);
- test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
- test_eq(rs->addr, 0x99009901);
- test_eq(rs->or_port, 443);
- test_eq(rs->dir_port, 0);
+ tt_mem_op(rs->descriptor_digest,==, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
+ tt_int_op(rs->addr,==, 0x99009901);
+ tt_int_op(rs->or_port,==, 443);
+ tt_int_op(rs->dir_port,==, 0);
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
- test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
- test_eq(rs->ipv6_orport, 4711);
- test_assert(rs->has_bandwidth);
- test_assert(vrs->has_measured_bw);
- test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb * 2);
- test_eq(vrs->measured_bw_kb, max_unmeasured_bw_kb * 2);
+ tt_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
+ tt_int_op(rs->ipv6_orport,==, 4711);
+ tt_assert(rs->has_bandwidth);
+ tt_assert(vrs->has_measured_bw);
+ tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb * 2);
+ tt_int_op(vrs->measured_bw_kb,==, max_unmeasured_bw_kb * 2);
} else if (tor_memeq(rs->identity_digest,
"\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33"
"\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33",
@@ -2065,10 +2601,10 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now)
* cutoff; this one should be clipped later on in the consensus, but
* appears unclipped in the vote.
*/
- test_assert(rs->has_bandwidth);
- test_assert(!(vrs->has_measured_bw));
- test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb * 2);
- test_eq(vrs->measured_bw_kb, 0);
+ tt_assert(rs->has_bandwidth);
+ tt_assert(!(vrs->has_measured_bw));
+ tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb * 2);
+ tt_int_op(vrs->measured_bw_kb,==, 0);
} else if (tor_memeq(rs->identity_digest,
"\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34"
"\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34",
@@ -2077,12 +2613,12 @@ test_vrs_for_umbw(vote_routerstatus_t *vrs, int voter, time_t now)
* Check the fourth routerstatus - unmeasured bandwidth below the clip
* cutoff; this one should not be clipped.
*/
- test_assert(rs->has_bandwidth);
- test_assert(!(vrs->has_measured_bw));
- test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb / 2);
- test_eq(vrs->measured_bw_kb, 0);
+ tt_assert(rs->has_bandwidth);
+ tt_assert(!(vrs->has_measured_bw));
+ tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb / 2);
+ tt_int_op(vrs->measured_bw_kb,==, 0);
} else {
- test_assert(0);
+ tt_assert(0);
}
done:
@@ -2097,11 +2633,11 @@ test_consensus_for_umbw(networkstatus_t *con, time_t now)
{
(void)now;
- test_assert(con);
- test_assert(!con->cert);
- // test_assert(con->consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB);
- test_assert(con->consensus_method >= 16);
- test_eq(4, smartlist_len(con->routerstatus_list));
+ tt_assert(con);
+ tt_assert(!con->cert);
+ // tt_assert(con->consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB);
+ tt_assert(con->consensus_method >= 16);
+ tt_int_op(4,==, smartlist_len(con->routerstatus_list));
/* There should be four listed routers; all voters saw the same in this */
done:
@@ -2118,61 +2654,61 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now)
uint32_t max_unmeasured_bw_kb = (alternate_clip_bw > 0) ?
alternate_clip_bw : DEFAULT_MAX_UNMEASURED_BW_KB;
- test_assert(rs);
+ tt_assert(rs);
/* There should be four listed routers, as constructed above */
if (tor_memeq(rs->identity_digest,
"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"
"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3",
DIGEST_LEN)) {
- test_memeq(rs->identity_digest,
+ tt_mem_op(rs->identity_digest,==,
"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"
"\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3",
DIGEST_LEN);
- test_memeq(rs->descriptor_digest, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN);
- test_assert(!rs->is_authority);
- test_assert(!rs->is_exit);
- test_assert(!rs->is_fast);
- test_assert(!rs->is_possible_guard);
- test_assert(!rs->is_stable);
+ tt_mem_op(rs->descriptor_digest,==, "NNNNNNNNNNNNNNNNNNNN", DIGEST_LEN);
+ tt_assert(!rs->is_authority);
+ tt_assert(!rs->is_exit);
+ tt_assert(!rs->is_fast);
+ tt_assert(!rs->is_possible_guard);
+ tt_assert(!rs->is_stable);
/* (If it wasn't running it wouldn't be here) */
- test_assert(rs->is_flagged_running);
- test_assert(!rs->is_valid);
- test_assert(!rs->is_named);
+ tt_assert(rs->is_flagged_running);
+ tt_assert(!rs->is_valid);
+ tt_assert(!rs->is_named);
/* This one should have measured bandwidth below the clip cutoff */
- test_assert(rs->has_bandwidth);
- test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb / 2);
- test_assert(!(rs->bw_is_unmeasured));
+ tt_assert(rs->has_bandwidth);
+ tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb / 2);
+ tt_assert(!(rs->bw_is_unmeasured));
} else if (tor_memeq(rs->identity_digest,
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5"
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5",
DIGEST_LEN)) {
/* This one showed up in 3 digests. Twice with ID 'M', once with 'Z'. */
- test_memeq(rs->identity_digest,
+ tt_mem_op(rs->identity_digest,==,
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5"
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5",
DIGEST_LEN);
- test_streq(rs->nickname, "router1");
- test_memeq(rs->descriptor_digest, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
- test_eq(rs->published_on, now-1000);
- test_eq(rs->addr, 0x99009901);
- test_eq(rs->or_port, 443);
- test_eq(rs->dir_port, 0);
+ tt_str_op(rs->nickname,==, "router1");
+ tt_mem_op(rs->descriptor_digest,==, "MMMMMMMMMMMMMMMMMMMM", DIGEST_LEN);
+ tt_int_op(rs->published_on,==, now-1000);
+ tt_int_op(rs->addr,==, 0x99009901);
+ tt_int_op(rs->or_port,==, 443);
+ tt_int_op(rs->dir_port,==, 0);
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
- test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
- test_eq(rs->ipv6_orport, 4711);
- test_assert(!rs->is_authority);
- test_assert(rs->is_exit);
- test_assert(rs->is_fast);
- test_assert(rs->is_possible_guard);
- test_assert(rs->is_stable);
- test_assert(rs->is_flagged_running);
- test_assert(rs->is_valid);
- test_assert(!rs->is_named);
+ tt_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
+ tt_int_op(rs->ipv6_orport,==, 4711);
+ tt_assert(!rs->is_authority);
+ tt_assert(rs->is_exit);
+ tt_assert(rs->is_fast);
+ tt_assert(rs->is_possible_guard);
+ tt_assert(rs->is_stable);
+ tt_assert(rs->is_flagged_running);
+ tt_assert(rs->is_valid);
+ tt_assert(!rs->is_named);
/* This one should have measured bandwidth above the clip cutoff */
- test_assert(rs->has_bandwidth);
- test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb * 2);
- test_assert(!(rs->bw_is_unmeasured));
+ tt_assert(rs->has_bandwidth);
+ tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb * 2);
+ tt_assert(!(rs->bw_is_unmeasured));
} else if (tor_memeq(rs->identity_digest,
"\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33"
"\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33",
@@ -2181,9 +2717,9 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now)
* This one should have unmeasured bandwidth above the clip cutoff,
* and so should be clipped
*/
- test_assert(rs->has_bandwidth);
- test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb);
- test_assert(rs->bw_is_unmeasured);
+ tt_assert(rs->has_bandwidth);
+ tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb);
+ tt_assert(rs->bw_is_unmeasured);
} else if (tor_memeq(rs->identity_digest,
"\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34"
"\x34\x34\x34\x34\x34\x34\x34\x34\x34\x34",
@@ -2192,12 +2728,12 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now)
* This one should have unmeasured bandwidth below the clip cutoff,
* and so should not be clipped
*/
- test_assert(rs->has_bandwidth);
- test_eq(rs->bandwidth_kb, max_unmeasured_bw_kb / 2);
- test_assert(rs->bw_is_unmeasured);
+ tt_assert(rs->has_bandwidth);
+ tt_int_op(rs->bandwidth_kb,==, max_unmeasured_bw_kb / 2);
+ tt_assert(rs->bw_is_unmeasured);
} else {
/* Weren't expecting this... */
- test_assert(0);
+ tt_assert(0);
}
done:
@@ -2211,9 +2747,10 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now)
*/
static void
-test_dir_clip_unmeasured_bw_kb(void)
+test_dir_clip_unmeasured_bw_kb(void *arg)
{
/* Run the test with the default clip bandwidth */
+ (void)arg;
alternate_clip_bw = 0;
test_a_networkstatus(gen_routerstatus_for_umbw,
vote_tweaks_for_umbw,
@@ -2228,7 +2765,7 @@ test_dir_clip_unmeasured_bw_kb(void)
*/
static void
-test_dir_clip_unmeasured_bw_kb_alt(void)
+test_dir_clip_unmeasured_bw_kb_alt(void *arg)
{
/*
* Try a different one; this value is chosen so that the below-the-cutoff
@@ -2236,6 +2773,7 @@ test_dir_clip_unmeasured_bw_kb_alt(void)
* DEFAULT_MAX_UNMEASURED_BW_KB and if the consensus incorrectly uses that
* cutoff it will fail the test.
*/
+ (void)arg;
alternate_clip_bw = 3 * DEFAULT_MAX_UNMEASURED_BW_KB;
test_a_networkstatus(gen_routerstatus_for_umbw,
vote_tweaks_for_umbw,
@@ -2286,60 +2824,60 @@ test_dir_http_handling(void *args)
/* Parse http url tests: */
/* Good headers */
- test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1\r\n"
+ tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1\r\n"
"Host: example.com\r\n"
"User-Agent: Mozilla/5.0 (Windows;"
" U; Windows NT 6.1; en-US; rv:1.9.1.5)\r\n",
- &url), 0);
- test_streq(url, "/tor/a/b/c.txt");
+ &url),==, 0);
+ tt_str_op(url,==, "/tor/a/b/c.txt");
tor_free(url);
- test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.0\r\n", &url), 0);
- test_streq(url, "/tor/a/b/c.txt");
+ tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.0\r\n", &url),==, 0);
+ tt_str_op(url,==, "/tor/a/b/c.txt");
tor_free(url);
- test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.600\r\n", &url), 0);
- test_streq(url, "/tor/a/b/c.txt");
+ tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.600\r\n", &url),==, 0);
+ tt_str_op(url,==, "/tor/a/b/c.txt");
tor_free(url);
/* Should prepend '/tor/' to url if required */
- test_eq(parse_http_url("GET /a/b/c.txt HTTP/1.1\r\n"
+ tt_int_op(parse_http_url("GET /a/b/c.txt HTTP/1.1\r\n"
"Host: example.com\r\n"
"User-Agent: Mozilla/5.0 (Windows;"
" U; Windows NT 6.1; en-US; rv:1.9.1.5)\r\n",
- &url), 0);
- test_streq(url, "/tor/a/b/c.txt");
+ &url),==, 0);
+ tt_str_op(url,==, "/tor/a/b/c.txt");
tor_free(url);
/* Bad headers -- no HTTP/1.x*/
- test_eq(parse_http_url("GET /a/b/c.txt\r\n"
+ tt_int_op(parse_http_url("GET /a/b/c.txt\r\n"
"Host: example.com\r\n"
"User-Agent: Mozilla/5.0 (Windows;"
" U; Windows NT 6.1; en-US; rv:1.9.1.5)\r\n",
- &url), -1);
+ &url),==, -1);
tt_assert(!url);
/* Bad headers */
- test_eq(parse_http_url("GET /a/b/c.txt\r\n"
+ tt_int_op(parse_http_url("GET /a/b/c.txt\r\n"
"Host: example.com\r\n"
"User-Agent: Mozilla/5.0 (Windows;"
" U; Windows NT 6.1; en-US; rv:1.9.1.5)\r\n",
- &url), -1);
+ &url),==, -1);
tt_assert(!url);
- test_eq(parse_http_url("GET /tor/a/b/c.txt", &url), -1);
+ tt_int_op(parse_http_url("GET /tor/a/b/c.txt", &url),==, -1);
tt_assert(!url);
- test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1", &url), -1);
+ tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1", &url),==, -1);
tt_assert(!url);
- test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1x\r\n", &url), -1);
+ tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.1x\r\n", &url),==, -1);
tt_assert(!url);
- test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.", &url), -1);
+ tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.", &url),==, -1);
tt_assert(!url);
- test_eq(parse_http_url("GET /tor/a/b/c.txt HTTP/1.\r", &url), -1);
+ tt_int_op(parse_http_url("GET /tor/a/b/c.txt HTTP/1.\r", &url),==, -1);
tt_assert(!url);
done:
@@ -2347,7 +2885,7 @@ test_dir_http_handling(void *args)
}
#define DIR_LEGACY(name) \
- { #name, legacy_test_helper, TT_FORK, &legacy_setup, test_dir_ ## name }
+ { #name, test_dir_ ## name , TT_FORK, NULL, NULL }
#define DIR(name,flags) \
{ #name, test_dir_##name, (flags), NULL, NULL }
@@ -2355,6 +2893,11 @@ test_dir_http_handling(void *args)
struct testcase_t dir_tests[] = {
DIR_LEGACY(nicknames),
DIR_LEGACY(formats),
+ DIR(routerparse_bad, 0),
+ DIR(extrainfo_parsing, 0),
+ DIR(parse_router_list, TT_FORK),
+ DIR(load_routers, TT_FORK),
+ DIR(load_extrainfo, TT_FORK),
DIR_LEGACY(versions),
DIR_LEGACY(fp_pairs),
DIR(split_fps, 0),
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index fab82c3446..bddc0f11e0 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -139,7 +139,7 @@ test_choose_random_entry_no_guards(void *arg)
/* Unintuitively, we actually pick a random node as our entry,
because router_choose_random_node() relaxes its constraints if it
can't find a proper entry guard. */
- test_assert(chosen_entry);
+ tt_assert(chosen_entry);
done:
;
@@ -201,7 +201,7 @@ populate_live_entry_guards_test_helper(int num_needed)
SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) {
const node_t *node_tmp;
node_tmp = add_an_entry_guard(node, 0, 1, 0, 0);
- test_assert(node_tmp);
+ tt_assert(node_tmp);
} SMARTLIST_FOREACH_END(node);
/* Make sure the nodes were added as entry guards. */
@@ -650,7 +650,7 @@ test_entry_is_live(void *arg)
SMARTLIST_FOREACH_BEGIN(our_nodelist, const node_t *, node) {
const node_t *node_tmp;
node_tmp = add_an_entry_guard(node, 0, 1, 0, 0);
- test_assert(node_tmp);
+ tt_assert(node_tmp);
tt_int_op(node->is_stable, ==, 0);
tt_int_op(node->is_fast, ==, 0);
@@ -670,22 +670,22 @@ test_entry_is_live(void *arg)
test_node = entry_is_live(test_entry,
ENTRY_NEED_UPTIME | ENTRY_ASSUME_REACHABLE,
&msg);
- test_assert(!test_node);
+ tt_assert(!test_node);
/* Require the node to be fast, but it's not. Should fail. */
test_node = entry_is_live(test_entry,
ENTRY_NEED_CAPACITY | ENTRY_ASSUME_REACHABLE,
&msg);
- test_assert(!test_node);
+ tt_assert(!test_node);
/* Don't impose any restrictions on the node. Should succeed. */
test_node = entry_is_live(test_entry, 0, &msg);
- test_assert(test_node);
+ tt_assert(test_node);
tt_ptr_op(test_node, ==, node_get_by_id(test_entry->identity));
/* Require descriptor for this node. It has one so it should succeed. */
test_node = entry_is_live(test_entry, ENTRY_NEED_DESCRIPTOR, &msg);
- test_assert(test_node);
+ tt_assert(test_node);
tt_ptr_op(test_node, ==, node_get_by_id(test_entry->identity));
done:
diff --git a/src/test/test_extorport.c b/src/test/test_extorport.c
index 93c8f77d5b..35e7fe5ad9 100644
--- a/src/test/test_extorport.c
+++ b/src/test/test_extorport.c
@@ -42,7 +42,7 @@ test_ext_or_id_map(void *arg)
/* Give c2 a new ID. */
connection_or_set_ext_or_identifier(c2);
- test_mem_op(idp, !=, c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
+ tt_mem_op(idp, !=, c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
idp2 = tor_memdup(c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
tt_assert(!tor_digest_is_zero(idp2));
@@ -119,7 +119,7 @@ test_ext_or_write_command(void *arg)
==, 0);
cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
tt_int_op(sz, ==, 4);
- test_mem_op(cp, ==, "\x00\x99\x00\x00", 4);
+ tt_mem_op(cp, ==, "\x00\x99\x00\x00", 4);
tor_free(cp);
/* Medium command. */
@@ -127,7 +127,7 @@ test_ext_or_write_command(void *arg)
"Wai\0Hello", 9), ==, 0);
cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
tt_int_op(sz, ==, 13);
- test_mem_op(cp, ==, "\x00\x99\x00\x09Wai\x00Hello", 13);
+ tt_mem_op(cp, ==, "\x00\x99\x00\x09Wai\x00Hello", 13);
tor_free(cp);
/* Long command */
@@ -137,8 +137,8 @@ test_ext_or_write_command(void *arg)
buf, 65535), ==, 0);
cp = buf_get_contents(TO_CONN(c1)->outbuf, &sz);
tt_int_op(sz, ==, 65539);
- test_mem_op(cp, ==, "\xf0\x0d\xff\xff", 4);
- test_mem_op(cp+4, ==, buf, 65535);
+ tt_mem_op(cp, ==, "\xf0\x0d\xff\xff", 4);
+ tt_mem_op(cp+4, ==, buf, 65535);
tor_free(cp);
done:
@@ -181,7 +181,7 @@ test_ext_or_init_auth(void *arg)
/* Shouldn't be initialized already, or our tests will be a bit
* meaningless */
ext_or_auth_cookie = tor_malloc_zero(32);
- test_assert(tor_mem_is_zero((char*)ext_or_auth_cookie, 32));
+ tt_assert(tor_mem_is_zero((char*)ext_or_auth_cookie, 32));
/* Now make sure we use a temporary file */
fn = get_fname("ext_cookie_file");
@@ -203,14 +203,14 @@ test_ext_or_init_auth(void *arg)
cp = read_file_to_str(fn, RFTS_BIN, &st);
tt_ptr_op(cp, !=, NULL);
tt_u64_op((uint64_t)st.st_size, ==, 64);
- test_memeq(cp, "! Extended ORPort Auth Cookie !\x0a", 32);
- test_memeq(cp+32, ext_or_auth_cookie, 32);
+ tt_mem_op(cp,==, "! Extended ORPort Auth Cookie !\x0a", 32);
+ tt_mem_op(cp+32,==, ext_or_auth_cookie, 32);
memcpy(cookie0, ext_or_auth_cookie, 32);
- test_assert(!tor_mem_is_zero((char*)ext_or_auth_cookie, 32));
+ tt_assert(!tor_mem_is_zero((char*)ext_or_auth_cookie, 32));
/* Operation should be idempotent. */
tt_int_op(0, ==, init_ext_or_cookie_authentication(1));
- test_memeq(cookie0, ext_or_auth_cookie, 32);
+ tt_mem_op(cookie0,==, ext_or_auth_cookie, 32);
done:
tor_free(cp);
@@ -280,15 +280,15 @@ test_ext_or_cookie_auth(void *arg)
46+32+32);
crypto_hmac_sha256(hmac2, (char*)ext_or_auth_cookie, 32, client_hash_input,
46+32+32);
- test_memeq(hmac1, reply, 32);
- test_memeq(hmac2, client_hash, 32);
+ tt_mem_op(hmac1,==, reply, 32);
+ tt_mem_op(hmac2,==, client_hash, 32);
/* Now do it again and make sure that the results are *different* */
tt_int_op(0, ==,
handle_client_auth_nonce(client_nonce, 32, &client_hash2, &reply2,
&reply_len));
- test_memneq(reply2, reply, reply_len);
- test_memneq(client_hash2, client_hash, 32);
+ tt_mem_op(reply2,!=, reply, reply_len);
+ tt_mem_op(client_hash2,!=, client_hash, 32);
/* But that this one checks out too. */
memcpy(server_hash_input+46+32, reply2+32, 32);
memcpy(client_hash_input+46+32, reply2+32, 32);
@@ -297,8 +297,8 @@ test_ext_or_cookie_auth(void *arg)
46+32+32);
crypto_hmac_sha256(hmac2, (char*)ext_or_auth_cookie, 32, client_hash_input,
46+32+32);
- test_memeq(hmac1, reply2, 32);
- test_memeq(hmac2, client_hash2, 32);
+ tt_mem_op(hmac1,==, reply2, 32);
+ tt_mem_op(hmac2,==, client_hash2, 32);
done:
tor_free(reply);
@@ -339,7 +339,7 @@ test_ext_or_cookie_auth_testvec(void *arg)
&reply_len));
tt_ptr_op(reply, !=, NULL );
tt_uint_op(reply_len, ==, 64);
- test_memeq(reply+32, "te road There is always another ", 32);
+ tt_mem_op(reply+32,==, "te road There is always another ", 32);
/* HMACSHA256("Gliding wrapt in a brown mantle,"
* "ExtORPort authentication server-to-client hash"
* "But when I look ahead up the write road There is always another ");
@@ -406,7 +406,7 @@ handshake_start(or_connection_t *conn, int receiving)
tt_int_op(buf_datalen(TO_CONN(conn)->outbuf), ==, (n)); \
if ((n)) { \
fetch_from_buf(b, (n), TO_CONN(conn)->outbuf); \
- test_memeq(b, (s), (n)); \
+ tt_mem_op(b, ==, (s), (n)); \
} \
} while (0)
diff --git a/src/test/test_hs.c b/src/test/test_hs.c
index 99ef7dd570..0ee46c2a58 100644
--- a/src/test/test_hs.c
+++ b/src/test/test_hs.c
@@ -84,8 +84,8 @@ test_hs_desc_event(void *arg)
STR_HS_ID);
expected_msg = "650 HS_DESC REQUESTED "STR_HS_ADDR" NO_AUTH "\
STR_HSDIR_EXIST_LONGNAME" "STR_HS_ID"\r\n";
- test_assert(received_msg);
- test_streq(received_msg, expected_msg);
+ tt_assert(received_msg);
+ tt_str_op(received_msg,==, expected_msg);
tor_free(received_msg);
/* test received event */
@@ -93,8 +93,8 @@ test_hs_desc_event(void *arg)
control_event_hs_descriptor_received(&rend_query, HSDIR_EXIST_ID);
expected_msg = "650 HS_DESC RECEIVED "STR_HS_ADDR" BASIC_AUTH "\
STR_HSDIR_EXIST_LONGNAME"\r\n";
- test_assert(received_msg);
- test_streq(received_msg, expected_msg);
+ tt_assert(received_msg);
+ tt_str_op(received_msg,==, expected_msg);
tor_free(received_msg);
/* test failed event */
@@ -102,8 +102,8 @@ test_hs_desc_event(void *arg)
control_event_hs_descriptor_failed(&rend_query, HSDIR_NONE_EXIST_ID);
expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" STEALTH_AUTH "\
STR_HSDIR_NONE_EXIST_LONGNAME"\r\n";
- test_assert(received_msg);
- test_streq(received_msg, expected_msg);
+ tt_assert(received_msg);
+ tt_str_op(received_msg,==, expected_msg);
tor_free(received_msg);
/* test invalid auth type */
@@ -111,8 +111,8 @@ test_hs_desc_event(void *arg)
control_event_hs_descriptor_failed(&rend_query, HSDIR_EXIST_ID);
expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" UNKNOWN "\
STR_HSDIR_EXIST_LONGNAME"\r\n";
- test_assert(received_msg);
- test_streq(received_msg, expected_msg);
+ tt_assert(received_msg);
+ tt_str_op(received_msg,==, expected_msg);
tor_free(received_msg);
done:
diff --git a/src/test/test_introduce.c b/src/test/test_introduce.c
index 69c1152229..17ee01d9b8 100644
--- a/src/test/test_introduce.c
+++ b/src/test/test_introduce.c
@@ -290,48 +290,48 @@ do_parse_test(uint8_t *plaintext, size_t plaintext_len, int phase)
/* Get a key */
k = crypto_pk_new();
- test_assert(k);
+ tt_assert(k);
r = crypto_pk_read_private_key_from_string(k, AUTHORITY_SIGNKEY_1, -1);
- test_assert(!r);
+ tt_assert(!r);
/* Get digest for future comparison */
r = crypto_pk_get_digest(k, digest);
- test_assert(r >= 0);
+ tt_assert(r >= 0);
/* Make a cell out of it */
r = make_intro_from_plaintext(
plaintext, plaintext_len,
k, (void **)(&cell));
- test_assert(r > 0);
- test_assert(cell);
+ tt_assert(r > 0);
+ tt_assert(cell);
cell_len = r;
/* Do early parsing */
parsed_req = rend_service_begin_parse_intro(cell, cell_len, 2, &err_msg);
- test_assert(parsed_req);
- test_assert(!err_msg);
- test_memeq(parsed_req->pk, digest, DIGEST_LEN);
- test_assert(parsed_req->ciphertext);
- test_assert(parsed_req->ciphertext_len > 0);
+ tt_assert(parsed_req);
+ tt_assert(!err_msg);
+ tt_mem_op(parsed_req->pk,==, digest, DIGEST_LEN);
+ tt_assert(parsed_req->ciphertext);
+ tt_assert(parsed_req->ciphertext_len > 0);
if (phase == EARLY_PARSE_ONLY)
goto done;
/* Do decryption */
r = rend_service_decrypt_intro(parsed_req, k, &err_msg);
- test_assert(!r);
- test_assert(!err_msg);
- test_assert(parsed_req->plaintext);
- test_assert(parsed_req->plaintext_len > 0);
+ tt_assert(!r);
+ tt_assert(!err_msg);
+ tt_assert(parsed_req->plaintext);
+ tt_assert(parsed_req->plaintext_len > 0);
if (phase == DECRYPT_ONLY)
goto done;
/* Do late parsing */
r = rend_service_parse_intro_plaintext(parsed_req, &err_msg);
- test_assert(!r);
- test_assert(!err_msg);
- test_assert(parsed_req->parsed);
+ tt_assert(!r);
+ tt_assert(!err_msg);
+ tt_assert(parsed_req->parsed);
done:
tor_free(cell);
@@ -371,14 +371,14 @@ make_intro_from_plaintext(
/* Compute key digest (will be first DIGEST_LEN octets of cell) */
r = crypto_pk_get_digest(key, cell);
- test_assert(r >= 0);
+ tt_assert(r >= 0);
/* Do encryption */
r = crypto_pk_public_hybrid_encrypt(
key, cell + DIGEST_LEN, ciphertext_size,
buf, len,
PK_PKCS1_OAEP_PADDING, 0);
- test_assert(r >= 0);
+ tt_assert(r >= 0);
/* Figure out cell length */
cell_len = DIGEST_LEN + r;
@@ -394,8 +394,9 @@ make_intro_from_plaintext(
*/
static void
-test_introduce_decrypt_v0(void)
+test_introduce_decrypt_v0(void *arg)
{
+ (void)arg;
do_decrypt_test(v0_test_plaintext, sizeof(v0_test_plaintext));
}
@@ -403,8 +404,9 @@ test_introduce_decrypt_v0(void)
*/
static void
-test_introduce_decrypt_v1(void)
+test_introduce_decrypt_v1(void *arg)
{
+ (void)arg;
do_decrypt_test(v1_test_plaintext, sizeof(v1_test_plaintext));
}
@@ -412,8 +414,9 @@ test_introduce_decrypt_v1(void)
*/
static void
-test_introduce_decrypt_v2(void)
+test_introduce_decrypt_v2(void *arg)
{
+ (void)arg;
do_decrypt_test(v2_test_plaintext, sizeof(v2_test_plaintext));
}
@@ -421,8 +424,9 @@ test_introduce_decrypt_v2(void)
*/
static void
-test_introduce_decrypt_v3(void)
+test_introduce_decrypt_v3(void *arg)
{
+ (void)arg;
do_decrypt_test(
v3_no_auth_test_plaintext, sizeof(v3_no_auth_test_plaintext));
do_decrypt_test(
@@ -433,8 +437,9 @@ test_introduce_decrypt_v3(void)
*/
static void
-test_introduce_early_parse_v0(void)
+test_introduce_early_parse_v0(void *arg)
{
+ (void)arg;
do_early_parse_test(v0_test_plaintext, sizeof(v0_test_plaintext));
}
@@ -442,8 +447,9 @@ test_introduce_early_parse_v0(void)
*/
static void
-test_introduce_early_parse_v1(void)
+test_introduce_early_parse_v1(void *arg)
{
+ (void)arg;
do_early_parse_test(v1_test_plaintext, sizeof(v1_test_plaintext));
}
@@ -451,8 +457,9 @@ test_introduce_early_parse_v1(void)
*/
static void
-test_introduce_early_parse_v2(void)
+test_introduce_early_parse_v2(void *arg)
{
+ (void)arg;
do_early_parse_test(v2_test_plaintext, sizeof(v2_test_plaintext));
}
@@ -460,8 +467,9 @@ test_introduce_early_parse_v2(void)
*/
static void
-test_introduce_early_parse_v3(void)
+test_introduce_early_parse_v3(void *arg)
{
+ (void)arg;
do_early_parse_test(
v3_no_auth_test_plaintext, sizeof(v3_no_auth_test_plaintext));
do_early_parse_test(
@@ -472,8 +480,9 @@ test_introduce_early_parse_v3(void)
*/
static void
-test_introduce_late_parse_v0(void)
+test_introduce_late_parse_v0(void *arg)
{
+ (void)arg;
do_late_parse_test(v0_test_plaintext, sizeof(v0_test_plaintext));
}
@@ -481,8 +490,9 @@ test_introduce_late_parse_v0(void)
*/
static void
-test_introduce_late_parse_v1(void)
+test_introduce_late_parse_v1(void *arg)
{
+ (void)arg;
do_late_parse_test(v1_test_plaintext, sizeof(v1_test_plaintext));
}
@@ -490,8 +500,9 @@ test_introduce_late_parse_v1(void)
*/
static void
-test_introduce_late_parse_v2(void)
+test_introduce_late_parse_v2(void *arg)
{
+ (void)arg;
do_late_parse_test(v2_test_plaintext, sizeof(v2_test_plaintext));
}
@@ -499,8 +510,9 @@ test_introduce_late_parse_v2(void)
*/
static void
-test_introduce_late_parse_v3(void)
+test_introduce_late_parse_v3(void *arg)
{
+ (void)arg;
do_late_parse_test(
v3_no_auth_test_plaintext, sizeof(v3_no_auth_test_plaintext));
do_late_parse_test(
@@ -508,7 +520,7 @@ test_introduce_late_parse_v3(void)
}
#define INTRODUCE_LEGACY(name) \
- { #name, legacy_test_helper, 0, &legacy_setup, test_introduce_ ## name }
+ { #name, test_introduce_ ## name , 0, NULL, NULL }
struct testcase_t introduce_tests[] = {
INTRODUCE_LEGACY(early_parse_v0),
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
index 78f4823b87..bc6755b93e 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -7,11 +7,16 @@
#include "config.h"
#include "dirvote.h"
#include "microdesc.h"
+#include "networkstatus.h"
#include "routerlist.h"
#include "routerparse.h"
#include "test.h"
+#include <openssl/rsa.h>
+#include <openssl/bn.h>
+#include <openssl/pem.h>
+
#ifdef _WIN32
/* For mkdir() */
#include <direct.h>
@@ -108,7 +113,7 @@ test_md_cache(void *data)
md2 = smartlist_get(added, 0);
/* And it should have gotten removed from 'wanted' */
tt_int_op(smartlist_len(wanted), ==, 1);
- test_mem_op(smartlist_get(wanted, 0), ==, d3, DIGEST256_LEN);
+ tt_mem_op(smartlist_get(wanted, 0), ==, d3, DIGEST256_LEN);
smartlist_free(added);
added = NULL;
@@ -144,18 +149,18 @@ test_md_cache(void *data)
tt_int_op(md1->bodylen, ==, strlen(test_md1));
tt_int_op(md2->bodylen, ==, strlen(test_md2));
tt_int_op(md3->bodylen, ==, strlen(test_md3_noannotation));
- test_mem_op(md1->body, ==, test_md1, strlen(test_md1));
- test_mem_op(md2->body, ==, test_md2, strlen(test_md2));
- test_mem_op(md3->body, ==, test_md3_noannotation,
+ tt_mem_op(md1->body, ==, test_md1, strlen(test_md1));
+ tt_mem_op(md2->body, ==, test_md2, strlen(test_md2));
+ tt_mem_op(md3->body, ==, test_md3_noannotation,
strlen(test_md3_noannotation));
tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs.new",
options->DataDirectory);
s = read_file_to_str(fn, RFTS_BIN, NULL);
tt_assert(s);
- test_mem_op(md1->body, ==, s + md1->off, md1->bodylen);
- test_mem_op(md2->body, ==, s + md2->off, md2->bodylen);
- test_mem_op(md3->body, ==, s + md3->off, md3->bodylen);
+ tt_mem_op(md1->body, ==, s + md1->off, md1->bodylen);
+ tt_mem_op(md2->body, ==, s + md2->off, md2->bodylen);
+ tt_mem_op(md3->body, ==, s + md3->off, md3->bodylen);
tt_ptr_op(md1->family, ==, NULL);
tt_ptr_op(md3->family, !=, NULL);
@@ -180,9 +185,9 @@ test_md_cache(void *data)
tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs",
options->DataDirectory);
s = read_file_to_str(fn, RFTS_BIN, NULL);
- test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
- test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
- test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
+ tt_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
+ tt_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
+ tt_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
/* Okay, now we are going to forget about the cache entirely, and reload it
* from the disk. */
@@ -191,12 +196,12 @@ test_md_cache(void *data)
md1 = microdesc_cache_lookup_by_digest256(mc, d1);
md2 = microdesc_cache_lookup_by_digest256(mc, d2);
md3 = microdesc_cache_lookup_by_digest256(mc, d3);
- test_assert(md1);
- test_assert(md2);
- test_assert(md3);
- test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
- test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
- test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
+ tt_assert(md1);
+ tt_assert(md2);
+ tt_assert(md3);
+ tt_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
+ tt_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
+ tt_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
tt_int_op(md1->last_listed, ==, time1);
tt_int_op(md2->last_listed, ==, time2);
@@ -367,7 +372,7 @@ test_md_generate(void *arg)
microdesc_t *md = NULL;
(void)arg;
- ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL);
+ ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL, NULL);
tt_assert(ri);
md = dirvote_create_microdescriptor(ri, 8);
tt_str_op(md->body, ==, test_md_8);
@@ -391,10 +396,330 @@ test_md_generate(void *arg)
routerinfo_free(ri);
}
+/* Taken at random from my ~/.tor/cached-microdescs file and then
+ * hand-munged */
+static const char MD_PARSE_TEST_DATA[] =
+ /* Good 0 */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANsKd1GRfOuSR1MkcwKqs6SVy4Gi/JXplt/bHDkIGm6Q96TeJ5uyVgUL\n"
+ "DBr/ij6+JqgVFeriuiMzHKREytzjdaTuKsKBFFpLwb+Ppcjr5nMIH/AR6/aHO8hW\n"
+ "T3B9lx5T6Kl7CqZ4yqXxYRHzn50EPTIZuz0y9se4J4gi9mLmL+pHAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "p accept 20-23,43,53,79-81,88,110,143,194,220,443,464,531,543-544\n"
+ "id rsa1024 GEo59/iR1GWSIWZDzXTd5QxtqnU\n"
+ /* Bad 0: I've messed with the onion-key in the second one. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMr4o/pflVwscx11vC1AKEADlKEqnhpvCIjAEzNEenMhvGQHRlA0EXLC\n"
+ "7G7O5bhnCwEHqK8Pvg8cuX/fD8v08TF1EVPhwPa0UI6ab8KnPP2F!!!!!!b92DG7EQIk3q\n"
+ "d68Uxp7E9/t3v1WWZjzDqvEe0par6ul+DKW6HMlTGebFo5Q4e8R1AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key 761Dmm27via7lXygNHM3l+oJLrYU2Nye0Uz4pkpipyY=\n"
+ "p accept 53\n"
+ "id rsa1024 3Y4fwXhtgkdGDZ5ef5mtb6TJRQQ\n"
+ /* Good 1 */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANsMSjVi3EX8ZHfm/dvPF6KdVR66k1tVul7Jp+dDbDajBYNhgKRzVCxy\n"
+ "Yac1CBuQjOqK89tKap9PQBnhF087eDrfaZDqYTLwB2W2sBJncVej15WEPXPRBifo\n"
+ "iFZ8337kgczkaY+IOfSuhtbOUyDOoDpRJheIKBNq0ZiTqtLbbadVAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key ncfiHJjSgdDEW/gc6q6/7idac7j+x7ejQrRm6i75pGA=\n"
+ "p accept 443,6660-6669,6697,7000-7001\n"
+ "id rsa1024 XXuLzw3mfBELEq3veXoNhdehwD4\n"
+ /* Good 2 */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANQfBlrHrh9F/CAOytrNFgi0ikWMW/HZxuoszF9X+AQ+MudR8bcxxOGl\n"
+ "1RFwb74s8E3uuzrCkNFvSw9Ar1L02F2DOX0gLsxEGuYC4Ave9NUteGqSqDyEJQUJ\n"
+ "KlfxCPn2qC9nvNT7wR/Dg2WRvAEKnJmkpb57N3+WSAOPLjKOFEz3AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
+ "id rsa1024 6y60AEI9a1PUUlRPO0YQT9WzrjI\n"
+ /* Bad 1: Here I've messed with the ntor key */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAPjy2HacU3jDNO5nTOFGSwNa0qKCNn4yhtrDVcAJ5alIQeBWZZGJLZ0q\n"
+ "Cqylw1vYqxu8E09g+QXXFbAgBv1U9TICaATxrIJhIJzc8TJPhqJemp1kq0DvHLDx\n"
+ "mxwlkNnCD/P5NS+JYB3EjOlU9EnSKUWNU61+Co344m2JqhEau40vAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key 4i2Fp9JHTUr1uQs0pxD5j5spl4/RG56S2P0gQxU=\n"
+ "id rsa1024 nMRmNEGysA0NmlALVaUmI7D5jLU\n"
+ /* Good 3: I've added a weird token in this one. This shouldn't prevent
+ * it parsing */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKmosxudyNA/yJNz3S890VqV/ebylzoD11Sc0b/d5tyNNaNZjcYy5vRD\n"
+ "kwyxFRMbP2TLZQ1zRfNwY7IDnYjU2SbW0pxuM6M8WRtsmx/YOE3kHMVAFJNrTUqU\n"
+ "6D1zB3IiRDS5q5+NoRxwqo+hYUck60O3WTwEoqb+l3lvXeu7z9rFAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "flux-capacitor 1.21 GW\n"
+ "ntor-onion-key MWBoEkl+RlBiGX44XKIvTSqbznTNZStOmUYtcYRQQyY=\n"
+ "id rsa1024 R+A5O9qRvRac4FT3C4L2QnFyxsc\n"
+ /* Good 4: Here I've made the 'id rsa' token odd. It should still parse
+ * just fine. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAOh+WMkdNe/Pkjb8UjQyfLOlFgpuVFrxAIGnJsmWWx0yBE97DQxGyh2n\n"
+ "h8G5OJZHRarJQyCIf7vpZQAi0oP0OkGGaCaDQsM+D8TnqhnU++RWGnMqY/cXxPrL\n"
+ "MEq+n6aGiLmzkO7ah8yorZpoREk4GqLUIN89/tHHGOhJL3c4CPGjAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
+ "id rsa1234 jlqAKFD2E7uMKv+8TmKSeo7NBho\n"
+ /* Good 5: Extra id type. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMdgPPc5uaw4y/q+SUTN/I8Y+Gvdx9kKgWV4dmDGJ0mxsVZmo1v6+v3F\n"
+ "12M2f9m99G3WB8F8now29C+9XyEv8MBHj1lHRdUFHSQes3YTFvDNlgj+FjLqO5TJ\n"
+ "adOOmfu4DCUUtUEDyQKbNVL4EkMTXY73omTVsjcH3xxFjTx5wixhAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key AAVnWZcnDbxasdZwKqb4fL6O9sZV+XsRNHTpNd1YMz8=\n"
+ "id rsa1024 72EfBL11QuwX2vU8y+p9ExGfGEg\n"
+ "id expolding hedgehog 0+A5O9qRvRac4FT3C4L2QnFyxsc\n"
+ /* Good 6: I've given this a bogus policy. It should parse. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALNuufwhPMF8BooxYMNvhYJMPqUB8hQDt8wGmPKphJcD1sVD1i4gAZM2\n"
+ "HIo+zUBlljDrRWL5NzVzd1yxUJAiQxvXS5dRRFY3B70M7wTVpXw53xe0/BM5t1AX\n"
+ "n0MFk7Jl6XIKMlzRalZvmMvE/odtyWXkP4Nd1MyZ1QcIwrQ2iwyrAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "p condone 1-10\n"
+ "ntor-onion-key 2/nMJ+L4dd/2GpMyTYjz3zC59MvQy4MIzJZhdzKHekg=\n"
+ "id rsa1024 FHyh10glEMA6MCmBb5R9Y+X/MhQ\n"
+ /* Good 7: I've given this one another sort of odd policy. Should parse. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAKcd3FmQ8iAADghyvX8eca0ePqtJ2w1IDdUdTlf5Y/8+OMdp//sD01yC\n"
+ "YmiX45LK5ge1O3AzcakYCO6fb3pyIqvXdvm24OjyYZELQ40cmKSLjdhcSf4Fr/N9\n"
+ "uR/CkknR9cEePu1wZ5WBIGmGdXI6s7t3LB+e7XFyBYAx6wMGlnX7AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "p accept frogs-mice\n"
+ "ntor-onion-key AMxvhaQ1Qg7jBJFoyHuPRgETvLbFmJ194hExV24FuAI=\n"
+ "family $D8CFEA0D996F5D1473D2063C041B7910DB23981E\n"
+ "id rsa1024 d0VVZC/cHh1P3y4MMbfKlQHFycc\n"
+ /* Good 8: This one has the ntor-onion-key without terminating =. That's
+ * allowed. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAL438YfjrJE2SPqkkXeQwICygu8KNO54Juj6sjqk5hgsiazIWMOBgbaX\n"
+ "LIRqPNGaiSq01xSqwjwCBCfwZYT/nSdDBqj1h9aoR8rnjxZjyQ+m3rWpdDqeCDMx\n"
+ "I3NgZ5w4bNX4poRb42lrV6NmQiFdjzpqszVbv5Lpn2CSKu32CwKVAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key UKL6Dnj2KwYsFlkCvOkXVatxvOPB4MaxqwPQQgZMTwI\n"
+ "id rsa1024 FPIXc6k++JnKCtSKWUxaR6oXEKs\n"
+ /* Good 9: Another totally normal one.*/
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANNGIKRd8PFNXkJ2JPV1ohDMFNbJwKbwybeieaQFjtU9KWedHCbr+QD4\n"
+ "B6zNY5ysguNjHNnlq2f6D09+uhnfDBON8tAz0mPQH/6JqnOXm+EiUn+8bN0E8Nke\n"
+ "/i3GEgDeaxJJMNQcpsJvmmSmKFOlYy9Fy7ejAjTGqtAnqOte7BnTAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key gUsq3e5iYgsQQvyxINtLzBpHxmIt5rtuFlEbKfI4gFk=\n"
+ "id rsa1024 jv+LdatDzsMfEW6pLBeL/5uzwCc\n"
+ /* Bad 2: RSA key has bad exponent of 3. */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGHAoGBAMMTWtvPxYnUNJ5Y7B+XENcpxzPoGstrdiUszCBS+/42xvluLJ+JDSdR\n"
+ "qJaMD6ax8vKAeLS5C6O17MNdG2VldlPRbtgl41MXsOoUqEJ+nY9e3WG9Snjp47xC\n"
+ "zmWIfeduXSavIsb3a43/MLIz/9qO0TkgAAiuQr79JlwKhLdzCqTLAgED\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key NkRB4wTUFogiVp5jYmjGORe2ffb/y5Kk8Itw8jdzMjA=\n"
+ "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
+ "id rsa1024 fKvYjP7TAjCC1FzYee5bYAwYkoDg\n"
+ /* Bad 3: Bogus annotation */
+ "@last-listed with strange aeons\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBALcRBFNCZtpd2TFJysU77/fJMFzKisRQEBOtDGtTZ2Bg4aEGosssa0Id\n"
+ "YtUagRLYle08QVGvGB+EHBI5qf6Ah2yPH7k5QiN2a3Sq+nyh85dXKPazBGBBbM+C\n"
+ "DOfDauV02CAnADNMLJEf1voY3oBVvYyIsmHxn5i1R19ZYIiR8NX5AgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key m4xcFXMWMjCvZDXq8FT3XmS0EHYseGOeu+fV+6FYDlk=\n"
+ "p accept 20-23,43,53,79-81,88,110,143,194,220,389,443,464,531,543-544\n"
+ "id rsa1024 SSbfNE9vmaiwRKH+eqNAkiKQhds\n"
+ /* Good 10: Normal, with added ipv6 address and added other address */
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n"
+ "sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
+ "+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "a [::1:2:3:4]:9090\n"
+ "a 18.0.0.1:9999\n"
+ "ntor-onion-key k2yFqTU2vzMCQDEiE/j9UcEHxKrXMLpB3IL0or09sik=\n"
+ "id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n"
+ "p6 allow 80\n"
+ ;
+
+/** More tests for parsing different kinds of microdescriptors, and getting
+ * invalid digests trackd from them. */
+static void
+test_md_parse(void *arg)
+{
+ (void) arg;
+ char *mem_op_hex_tmp = NULL;
+ smartlist_t *invalid = smartlist_new();
+
+ smartlist_t *mds = microdescs_parse_from_string(MD_PARSE_TEST_DATA,
+ NULL, 1, SAVED_NOWHERE,
+ invalid);
+ tt_int_op(smartlist_len(mds), ==, 11);
+ tt_int_op(smartlist_len(invalid), ==, 4);
+
+ test_memeq_hex(smartlist_get(invalid,0),
+ "5d76bf1c6614e885614a1e0ad074e1ab"
+ "4ea14655ebeefb1736a71b5ed8a15a51");
+ test_memeq_hex(smartlist_get(invalid,1),
+ "2fde0ee3343669c2444cd9d53cbd39c6"
+ "a7d1fc0513513e840ca7f6e68864b36c");
+ test_memeq_hex(smartlist_get(invalid,2),
+ "20d1576c5ab11bbcff0dedb1db4a3cfc"
+ "c8bc8dd839d8cbfef92d00a1a7d7b294");
+ test_memeq_hex(smartlist_get(invalid,3),
+ "074770f394c73dbde7b44412e9692add"
+ "691a478d4727f9804b77646c95420a96");
+
+ /* Spot-check the valid ones. */
+ const microdesc_t *md = smartlist_get(mds, 5);
+ test_memeq_hex(md->digest,
+ "54bb6d733ddeb375d2456c79ae103961"
+ "da0cae29620375ac4cf13d54da4d92b3");
+ tt_int_op(md->last_listed, ==, 0);
+ tt_int_op(md->saved_location, ==, SAVED_NOWHERE);
+ tt_int_op(md->no_save, ==, 0);
+ tt_uint_op(md->held_in_map, ==, 0);
+ tt_uint_op(md->held_by_nodes, ==, 0);
+ tt_assert(md->onion_curve25519_pkey);
+
+ md = smartlist_get(mds, 6);
+ test_memeq_hex(md->digest,
+ "53f740bd222ab37f19f604b1d3759aa6"
+ "5eff1fbce9ac254bd0fa50d4af9b1bae");
+ tt_assert(! md->exit_policy);
+
+ md = smartlist_get(mds, 8);
+ test_memeq_hex(md->digest,
+ "a0a155562d8093d8fd0feb7b93b7226e"
+ "17f056c2142aab7a4ea8c5867a0376d5");
+ tt_assert(md->onion_curve25519_pkey);
+
+ md = smartlist_get(mds, 10);
+ test_memeq_hex(md->digest,
+ "409ebd87d23925a2732bd467a92813c9"
+ "21ca378fcb9ca193d354c51550b6d5e9");
+ tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6);
+ tt_int_op(md->ipv6_orport, ==, 9090);
+
+ done:
+ SMARTLIST_FOREACH(mds, microdesc_t *, md, microdesc_free(md));
+ smartlist_free(mds);
+ SMARTLIST_FOREACH(invalid, char *, cp, tor_free(cp));
+ smartlist_free(invalid);
+ tor_free(mem_op_hex_tmp);
+}
+
+static int mock_rgsbd_called = 0;
+static routerstatus_t *mock_rgsbd_val_a = NULL;
+static routerstatus_t *mock_rgsbd_val_b = NULL;
+static routerstatus_t *
+mock_router_get_status_by_digest(networkstatus_t *c, const char *d)
+{
+ (void) c;
+ ++mock_rgsbd_called;
+
+ if (fast_memeq(d, "\x5d\x76", 2)) {
+ memcpy(mock_rgsbd_val_a->descriptor_digest, d, 32);
+ return mock_rgsbd_val_a;
+ } else if (fast_memeq(d, "\x20\xd1", 2)) {
+ memcpy(mock_rgsbd_val_b->descriptor_digest, d, 32);
+ return mock_rgsbd_val_b;
+ } else {
+ return NULL;
+ }
+}
+
+static networkstatus_t *mock_ns_val = NULL;
+static networkstatus_t *
+mock_ns_get_by_flavor(consensus_flavor_t f)
+{
+ (void)f;
+ return mock_ns_val;
+}
+
+static void
+test_md_reject_cache(void *arg)
+{
+ (void) arg;
+ microdesc_cache_t *mc = NULL ;
+ smartlist_t *added = NULL, *wanted = smartlist_new();
+ or_options_t *options = get_options_mutable();
+ char buf[DIGEST256_LEN];
+
+ tor_free(options->DataDirectory);
+ options->DataDirectory = tor_strdup(get_fname("md_datadir_test_rej"));
+ mock_rgsbd_val_a = tor_malloc_zero(sizeof(routerstatus_t));
+ mock_rgsbd_val_b = tor_malloc_zero(sizeof(routerstatus_t));
+ mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
+
+ mock_ns_val->valid_after = time(NULL) - 86400;
+ mock_ns_val->valid_until = time(NULL) + 86400;
+ mock_ns_val->flavor = FLAV_MICRODESC;
+
+#ifdef _WIN32
+ tt_int_op(0, ==, mkdir(options->DataDirectory));
+#else
+ tt_int_op(0, ==, mkdir(options->DataDirectory, 0700));
+#endif
+
+ MOCK(router_get_mutable_consensus_status_by_descriptor_digest,
+ mock_router_get_status_by_digest);
+ MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor);
+
+ mc = get_microdesc_cache();
+#define ADD(hex) \
+ do { \
+ tt_int_op(0,==,base16_decode(buf,sizeof(buf),hex,strlen(hex))); \
+ smartlist_add(wanted, tor_memdup(buf, DIGEST256_LEN)); \
+ } while (0)
+
+ /* invalid,0 */
+ ADD("5d76bf1c6614e885614a1e0ad074e1ab4ea14655ebeefb1736a71b5ed8a15a51");
+ /* invalid,2 */
+ ADD("20d1576c5ab11bbcff0dedb1db4a3cfcc8bc8dd839d8cbfef92d00a1a7d7b294");
+ /* valid, 6 */
+ ADD("53f740bd222ab37f19f604b1d3759aa65eff1fbce9ac254bd0fa50d4af9b1bae");
+ /* valid, 8 */
+ ADD("a0a155562d8093d8fd0feb7b93b7226e17f056c2142aab7a4ea8c5867a0376d5");
+
+ added = microdescs_add_to_cache(mc, MD_PARSE_TEST_DATA, NULL,
+ SAVED_NOWHERE, 0, time(NULL), wanted);
+
+ tt_int_op(smartlist_len(added), ==, 2);
+ tt_int_op(mock_rgsbd_called, ==, 2);
+ tt_int_op(mock_rgsbd_val_a->dl_status.n_download_failures, ==, 255);
+ tt_int_op(mock_rgsbd_val_b->dl_status.n_download_failures, ==, 255);
+
+ done:
+ UNMOCK(networkstatus_get_latest_consensus_by_flavor);
+ UNMOCK(router_get_mutable_consensus_status_by_descriptor_digest);
+ if (options)
+ tor_free(options->DataDirectory);
+ microdesc_free_all();
+ smartlist_free(added);
+ SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
+ smartlist_free(wanted);
+ tor_free(mock_rgsbd_val_a);
+ tor_free(mock_rgsbd_val_b);
+ tor_free(mock_ns_val);
+}
+
struct testcase_t microdesc_tests[] = {
{ "cache", test_md_cache, TT_FORK, NULL, NULL },
{ "broken_cache", test_md_cache_broken, TT_FORK, NULL, NULL },
{ "generate", test_md_generate, 0, NULL, NULL },
+ { "parse", test_md_parse, 0, NULL, NULL },
+ { "reject_cache", test_md_reject_cache, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_nodelist.c b/src/test/test_nodelist.c
index 600e6a89d4..6d270db960 100644
--- a/src/test/test_nodelist.c
+++ b/src/test/test_nodelist.c
@@ -23,9 +23,9 @@ test_nodelist_node_get_verbose_nickname_by_id_null_node(void *arg)
(void) arg;
/* make sure node_get_by_id returns NULL */
- test_assert(!node_get_by_id(ID));
+ tt_assert(!node_get_by_id(ID));
node_get_verbose_nickname_by_id(ID, vname);
- test_streq(vname, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
+ tt_str_op(vname,==, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
done:
return;
}
@@ -54,7 +54,7 @@ test_nodelist_node_get_verbose_nickname_not_named(void *arg)
"\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
DIGEST_LEN);
node_get_verbose_nickname(&mock_node, vname);
- test_streq(vname, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR");
+ tt_str_op(vname,==, "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~TestOR");
done:
return;
diff --git a/src/test/test_policy.c b/src/test/test_policy.c
index 4cdcd034bb..388251a61f 100644
--- a/src/test/test_policy.c
+++ b/src/test/test_policy.c
@@ -47,17 +47,20 @@ test_policy_summary_helper(const char *policy_str,
line.value = (char *)policy_str;
line.next = NULL;
- r = policies_parse_exit_policy(&line, &policy, 1, 0, 0, 1);
- test_eq(r, 0);
+ r = policies_parse_exit_policy(&line, &policy,
+ EXIT_POLICY_IPV6_ENABLED |
+ EXIT_POLICY_ADD_DEFAULT ,0);
+ tt_int_op(r,==, 0);
+
summary = policy_summarize(policy, AF_INET);
- test_assert(summary != NULL);
- test_streq(summary, expected_summary);
+ tt_assert(summary != NULL);
+ tt_str_op(summary,==, expected_summary);
short_policy = parse_short_policy(summary);
tt_assert(short_policy);
summary_after = write_short_policy(short_policy);
- test_streq(summary, summary_after);
+ tt_str_op(summary,==, summary_after);
done:
tor_free(summary_after);
@@ -86,104 +89,108 @@ test_policies_general(void *arg)
policy = smartlist_new();
p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1);
- test_assert(p != NULL);
- test_eq(ADDR_POLICY_REJECT, p->policy_type);
+ tt_assert(p != NULL);
+ tt_int_op(ADDR_POLICY_REJECT,==, p->policy_type);
tor_addr_from_ipv4h(&tar, 0xc0a80000u);
- test_eq(0, tor_addr_compare(&p->addr, &tar, CMP_EXACT));
- test_eq(16, p->maskbits);
- test_eq(1, p->prt_min);
- test_eq(65535, p->prt_max);
+ tt_int_op(0,==, tor_addr_compare(&p->addr, &tar, CMP_EXACT));
+ tt_int_op(16,==, p->maskbits);
+ tt_int_op(1,==, p->prt_min);
+ tt_int_op(65535,==, p->prt_max);
smartlist_add(policy, p);
tor_addr_from_ipv4h(&tar, 0x01020304u);
- test_assert(ADDR_POLICY_ACCEPTED ==
+ tt_assert(ADDR_POLICY_ACCEPTED ==
compare_tor_addr_to_addr_policy(&tar, 2, policy));
tor_addr_make_unspec(&tar);
- test_assert(ADDR_POLICY_PROBABLY_ACCEPTED ==
+ tt_assert(ADDR_POLICY_PROBABLY_ACCEPTED ==
compare_tor_addr_to_addr_policy(&tar, 2, policy));
tor_addr_from_ipv4h(&tar, 0xc0a80102);
- test_assert(ADDR_POLICY_REJECTED ==
+ tt_assert(ADDR_POLICY_REJECTED ==
compare_tor_addr_to_addr_policy(&tar, 2, policy));
- test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, 1, 0, 1));
- test_assert(policy2);
+ tt_int_op(0, ==, policies_parse_exit_policy(NULL, &policy2,
+ EXIT_POLICY_IPV6_ENABLED |
+ EXIT_POLICY_REJECT_PRIVATE |
+ EXIT_POLICY_ADD_DEFAULT, 0));
+
+ tt_assert(policy2);
policy3 = smartlist_new();
p = router_parse_addr_policy_item_from_string("reject *:*",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy3, p);
p = router_parse_addr_policy_item_from_string("accept *:*",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy3, p);
policy4 = smartlist_new();
p = router_parse_addr_policy_item_from_string("accept *:443",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy4, p);
p = router_parse_addr_policy_item_from_string("accept *:443",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy4, p);
policy5 = smartlist_new();
p = router_parse_addr_policy_item_from_string("reject 0.0.0.0/8:*",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy5, p);
p = router_parse_addr_policy_item_from_string("reject 169.254.0.0/16:*",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy5, p);
p = router_parse_addr_policy_item_from_string("reject 127.0.0.0/8:*",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy5, p);
p = router_parse_addr_policy_item_from_string("reject 192.168.0.0/16:*",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy5, p);
p = router_parse_addr_policy_item_from_string("reject 10.0.0.0/8:*",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy5, p);
p = router_parse_addr_policy_item_from_string("reject 172.16.0.0/12:*",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy5, p);
p = router_parse_addr_policy_item_from_string("reject 80.190.250.90:*",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy5, p);
p = router_parse_addr_policy_item_from_string("reject *:1-65534",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy5, p);
p = router_parse_addr_policy_item_from_string("reject *:65535",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy5, p);
p = router_parse_addr_policy_item_from_string("accept *:1-65535",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy5, p);
policy6 = smartlist_new();
p = router_parse_addr_policy_item_from_string("accept 43.3.0.0/9:*",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy6, p);
policy7 = smartlist_new();
p = router_parse_addr_policy_item_from_string("accept 0.0.0.0/8:*",-1);
- test_assert(p != NULL);
+ tt_assert(p != NULL);
smartlist_add(policy7, p);
- test_assert(!exit_policy_is_general_exit(policy));
- test_assert(exit_policy_is_general_exit(policy2));
- test_assert(!exit_policy_is_general_exit(NULL));
- test_assert(!exit_policy_is_general_exit(policy3));
- test_assert(!exit_policy_is_general_exit(policy4));
- test_assert(!exit_policy_is_general_exit(policy5));
- test_assert(!exit_policy_is_general_exit(policy6));
- test_assert(!exit_policy_is_general_exit(policy7));
+ tt_assert(!exit_policy_is_general_exit(policy));
+ tt_assert(exit_policy_is_general_exit(policy2));
+ tt_assert(!exit_policy_is_general_exit(NULL));
+ tt_assert(!exit_policy_is_general_exit(policy3));
+ tt_assert(!exit_policy_is_general_exit(policy4));
+ tt_assert(!exit_policy_is_general_exit(policy5));
+ tt_assert(!exit_policy_is_general_exit(policy6));
+ tt_assert(!exit_policy_is_general_exit(policy7));
- test_assert(cmp_addr_policies(policy, policy2));
- test_assert(cmp_addr_policies(policy, NULL));
- test_assert(!cmp_addr_policies(policy2, policy2));
- test_assert(!cmp_addr_policies(NULL, NULL));
+ tt_assert(cmp_addr_policies(policy, policy2));
+ tt_assert(cmp_addr_policies(policy, NULL));
+ tt_assert(!cmp_addr_policies(policy2, policy2));
+ tt_assert(!cmp_addr_policies(NULL, NULL));
- test_assert(!policy_is_reject_star(policy2, AF_INET));
- test_assert(policy_is_reject_star(policy, AF_INET));
- test_assert(policy_is_reject_star(NULL, AF_INET));
+ tt_assert(!policy_is_reject_star(policy2, AF_INET));
+ tt_assert(policy_is_reject_star(policy, AF_INET));
+ tt_assert(policy_is_reject_star(NULL, AF_INET));
addr_policy_list_free(policy);
policy = NULL;
@@ -193,11 +200,14 @@ test_policies_general(void *arg)
line.key = (char*)"foo";
line.value = (char*)"accept *:80,reject private:*,reject *:*";
line.next = NULL;
- test_assert(0 == policies_parse_exit_policy(&line, &policy, 1, 0, 0, 1));
- test_assert(policy);
+ tt_int_op(0, ==, policies_parse_exit_policy(&line,&policy,
+ EXIT_POLICY_IPV6_ENABLED |
+ EXIT_POLICY_ADD_DEFAULT,0));
+ tt_assert(policy);
+
//test_streq(policy->string, "accept *:80");
//test_streq(policy->next->string, "reject *:*");
- test_eq(smartlist_len(policy), 4);
+ tt_int_op(smartlist_len(policy),==, 4);
/* test policy summaries */
/* check if we properly ignore private IP addresses */
@@ -359,7 +369,7 @@ test_dump_exit_policy_to_string(void *arg)
ri->exit_policy = NULL; // expecting "reject *:*"
ep = router_dump_exit_policy_to_string(ri,1,1);
- test_streq("reject *:*",ep);
+ tt_str_op("reject *:*",==, ep);
tor_free(ep);
@@ -372,7 +382,7 @@ test_dump_exit_policy_to_string(void *arg)
ep = router_dump_exit_policy_to_string(ri,1,1);
- test_streq("accept *:*",ep);
+ tt_str_op("accept *:*",==, ep);
tor_free(ep);
@@ -382,7 +392,7 @@ test_dump_exit_policy_to_string(void *arg)
ep = router_dump_exit_policy_to_string(ri,1,1);
- test_streq("accept *:*\nreject *:25",ep);
+ tt_str_op("accept *:*\nreject *:25",==, ep);
tor_free(ep);
@@ -393,7 +403,7 @@ test_dump_exit_policy_to_string(void *arg)
ep = router_dump_exit_policy_to_string(ri,1,1);
- test_streq("accept *:*\nreject *:25\nreject 8.8.8.8:*",ep);
+ tt_str_op("accept *:*\nreject *:25\nreject 8.8.8.8:*",==, ep);
tor_free(ep);
policy_entry =
@@ -403,8 +413,8 @@ test_dump_exit_policy_to_string(void *arg)
ep = router_dump_exit_policy_to_string(ri,1,1);
- test_streq("accept *:*\nreject *:25\nreject 8.8.8.8:*\n"
- "reject6 [fc00::]/7:*",ep);
+ tt_str_op("accept *:*\nreject *:25\nreject 8.8.8.8:*\n"
+ "reject6 [fc00::]/7:*",==, ep);
tor_free(ep);
policy_entry =
@@ -414,8 +424,8 @@ test_dump_exit_policy_to_string(void *arg)
ep = router_dump_exit_policy_to_string(ri,1,1);
- test_streq("accept *:*\nreject *:25\nreject 8.8.8.8:*\n"
- "reject6 [fc00::]/7:*\naccept6 [c000::]/3:*",ep);
+ tt_str_op("accept *:*\nreject *:25\nreject 8.8.8.8:*\n"
+ "reject6 [fc00::]/7:*\naccept6 [c000::]/3:*",==, ep);
done:
diff --git a/src/test/test_pt.c b/src/test/test_pt.c
index f55c059580..61ade84e3a 100644
--- a/src/test/test_pt.c
+++ b/src/test/test_pt.c
@@ -27,75 +27,76 @@ reset_mp(managed_proxy_t *mp)
}
static void
-test_pt_parsing(void)
+test_pt_parsing(void *arg)
{
char line[200];
transport_t *transport = NULL;
tor_addr_t test_addr;
- managed_proxy_t *mp = tor_malloc(sizeof(managed_proxy_t));
+ managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
+ (void)arg;
mp->conf_state = PT_PROTO_INFANT;
mp->transports = smartlist_new();
/* incomplete cmethod */
strlcpy(line,"CMETHOD trebuchet",sizeof(line));
- test_assert(parse_cmethod_line(line, mp) < 0);
+ tt_assert(parse_cmethod_line(line, mp) < 0);
reset_mp(mp);
/* wrong proxy type */
strlcpy(line,"CMETHOD trebuchet dog 127.0.0.1:1999",sizeof(line));
- test_assert(parse_cmethod_line(line, mp) < 0);
+ tt_assert(parse_cmethod_line(line, mp) < 0);
reset_mp(mp);
/* wrong addrport */
strlcpy(line,"CMETHOD trebuchet socks4 abcd",sizeof(line));
- test_assert(parse_cmethod_line(line, mp) < 0);
+ tt_assert(parse_cmethod_line(line, mp) < 0);
reset_mp(mp);
/* correct line */
strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line));
- test_assert(parse_cmethod_line(line, mp) == 0);
- test_assert(smartlist_len(mp->transports) == 1);
+ tt_assert(parse_cmethod_line(line, mp) == 0);
+ tt_assert(smartlist_len(mp->transports) == 1);
transport = smartlist_get(mp->transports, 0);
/* test registered address of transport */
tor_addr_parse(&test_addr, "127.0.0.1");
- test_assert(tor_addr_eq(&test_addr, &transport->addr));
+ tt_assert(tor_addr_eq(&test_addr, &transport->addr));
/* test registered port of transport */
- test_assert(transport->port == 1999);
+ tt_assert(transport->port == 1999);
/* test registered SOCKS version of transport */
- test_assert(transport->socks_version == PROXY_SOCKS5);
+ tt_assert(transport->socks_version == PROXY_SOCKS5);
/* test registered name of transport */
- test_streq(transport->name, "trebuchet");
+ tt_str_op(transport->name,==, "trebuchet");
reset_mp(mp);
/* incomplete smethod */
strlcpy(line,"SMETHOD trebuchet",sizeof(line));
- test_assert(parse_smethod_line(line, mp) < 0);
+ tt_assert(parse_smethod_line(line, mp) < 0);
reset_mp(mp);
/* wrong addr type */
strlcpy(line,"SMETHOD trebuchet abcd",sizeof(line));
- test_assert(parse_smethod_line(line, mp) < 0);
+ tt_assert(parse_smethod_line(line, mp) < 0);
reset_mp(mp);
/* cowwect */
strlcpy(line,"SMETHOD trebuchy 127.0.0.2:2999",sizeof(line));
- test_assert(parse_smethod_line(line, mp) == 0);
- test_assert(smartlist_len(mp->transports) == 1);
+ tt_assert(parse_smethod_line(line, mp) == 0);
+ tt_assert(smartlist_len(mp->transports) == 1);
transport = smartlist_get(mp->transports, 0);
/* test registered address of transport */
tor_addr_parse(&test_addr, "127.0.0.2");
- test_assert(tor_addr_eq(&test_addr, &transport->addr));
+ tt_assert(tor_addr_eq(&test_addr, &transport->addr));
/* test registered port of transport */
- test_assert(transport->port == 2999);
+ tt_assert(transport->port == 2999);
/* test registered name of transport */
- test_streq(transport->name, "trebuchy");
+ tt_str_op(transport->name,==, "trebuchy");
reset_mp(mp);
@@ -103,7 +104,7 @@ test_pt_parsing(void)
strlcpy(line,"SMETHOD trebuchet 127.0.0.1:9999 "
"ARGS:counterweight=3,sling=snappy",
sizeof(line));
- test_assert(parse_smethod_line(line, mp) == 0);
+ tt_assert(parse_smethod_line(line, mp) == 0);
tt_int_op(1, ==, smartlist_len(mp->transports));
{
const transport_t *transport = smartlist_get(mp->transports, 0);
@@ -118,15 +119,15 @@ test_pt_parsing(void)
/* unsupported version */
strlcpy(line,"VERSION 666",sizeof(line));
- test_assert(parse_version(line, mp) < 0);
+ tt_assert(parse_version(line, mp) < 0);
/* incomplete VERSION */
strlcpy(line,"VERSION ",sizeof(line));
- test_assert(parse_version(line, mp) < 0);
+ tt_assert(parse_version(line, mp) < 0);
/* correct VERSION */
strlcpy(line,"VERSION 1",sizeof(line));
- test_assert(parse_version(line, mp) == 0);
+ tt_assert(parse_version(line, mp) == 0);
done:
reset_mp(mp);
@@ -187,11 +188,12 @@ test_pt_get_transport_options(void *arg)
}
static void
-test_pt_protocol(void)
+test_pt_protocol(void *arg)
{
char line[200];
managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
+ (void)arg;
mp->conf_state = PT_PROTO_LAUNCHED;
mp->transports = smartlist_new();
mp->argv = tor_calloc(sizeof(char *), 2);
@@ -201,32 +203,32 @@ test_pt_protocol(void)
strlcpy(line,"VERSION 1",sizeof(line));
handle_proxy_line(line, mp);
- test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
+ tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
strlcpy(line,"VERSION 1",sizeof(line));
handle_proxy_line(line, mp);
- test_assert(mp->conf_state == PT_PROTO_BROKEN);
+ tt_assert(mp->conf_state == PT_PROTO_BROKEN);
reset_mp(mp);
strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line));
handle_proxy_line(line, mp);
- test_assert(mp->conf_state == PT_PROTO_BROKEN);
+ tt_assert(mp->conf_state == PT_PROTO_BROKEN);
reset_mp(mp);
/* correct protocol run: */
strlcpy(line,"VERSION 1",sizeof(line));
handle_proxy_line(line, mp);
- test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
+ tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
strlcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999",sizeof(line));
handle_proxy_line(line, mp);
- test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
+ tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
strlcpy(line,"CMETHODS DONE",sizeof(line));
handle_proxy_line(line, mp);
- test_assert(mp->conf_state == PT_PROTO_CONFIGURED);
+ tt_assert(mp->conf_state == PT_PROTO_CONFIGURED);
done:
reset_mp(mp);
@@ -363,7 +365,7 @@ test_pt_configure_proxy(void *arg)
control_testing_set_global_event_mask(EVENT_TRANSPORT_LAUNCHED);
- mp = tor_malloc(sizeof(managed_proxy_t));
+ mp = tor_malloc_zero(sizeof(managed_proxy_t));
mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
mp->transports = smartlist_new();
mp->transports_to_launch = smartlist_new();
@@ -378,19 +380,19 @@ test_pt_configure_proxy(void *arg)
for (i = 0 ; i < 5 ; i++) {
retval = configure_proxy(mp);
/* retval should be zero because proxy hasn't finished configuring yet */
- test_assert(retval == 0);
+ tt_int_op(retval, ==, 0);
/* check the number of registered transports */
- test_assert(smartlist_len(mp->transports) == i+1);
+ tt_assert(smartlist_len(mp->transports) == i+1);
/* check that the mp is still waiting for transports */
- test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
+ tt_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
}
/* this last configure_proxy() should finalize the proxy configuration. */
retval = configure_proxy(mp);
/* retval should be 1 since the proxy finished configuring */
- test_assert(retval == 1);
+ tt_int_op(retval, ==, 1);
/* check the mp state */
- test_assert(mp->conf_state == PT_PROTO_COMPLETED);
+ tt_assert(mp->conf_state == PT_PROTO_COMPLETED);
tt_int_op(controlevent_n, ==, 5);
tt_int_op(controlevent_event, ==, EVENT_TRANSPORT_LAUNCHED);
@@ -416,7 +418,7 @@ test_pt_configure_proxy(void *arg)
/* Get the bindaddr for "mock1" and check it against the bindaddr
that the mocked tor_get_lines_from_handle() generated. */
transport_in_state = get_transport_in_state_by_name("mock1");
- test_assert(transport_in_state);
+ tt_assert(transport_in_state);
smartlist_split_string(transport_info_sl, transport_in_state->value,
NULL, 0, 0);
name_of_transport = smartlist_get(transport_info_sl, 0);
@@ -450,8 +452,86 @@ test_pt_configure_proxy(void *arg)
tor_free(mp);
}
+/* Test the get_pt_proxy_uri() function. */
+static void
+test_get_pt_proxy_uri(void *arg)
+{
+ or_options_t *options = get_options_mutable();
+ char *uri = NULL;
+ int ret;
+ (void) arg;
+
+ /* Test with no proxy. */
+ uri = get_pt_proxy_uri();
+ tt_assert(uri == NULL);
+
+ /* Test with a SOCKS4 proxy. */
+ options->Socks4Proxy = tor_strdup("192.0.2.1:1080");
+ ret = tor_addr_port_lookup(options->Socks4Proxy,
+ &options->Socks4ProxyAddr,
+ &options->Socks4ProxyPort);
+ tt_int_op(ret, ==, 0);
+ uri = get_pt_proxy_uri();
+ tt_str_op(uri, ==, "socks4a://192.0.2.1:1080");
+ tor_free(uri);
+ tor_free(options->Socks4Proxy);
+
+ /* Test with a SOCKS5 proxy, no username/password. */
+ options->Socks5Proxy = tor_strdup("192.0.2.1:1080");
+ ret = tor_addr_port_lookup(options->Socks5Proxy,
+ &options->Socks5ProxyAddr,
+ &options->Socks5ProxyPort);
+ tt_int_op(ret, ==, 0);
+ uri = get_pt_proxy_uri();
+ tt_str_op(uri, ==, "socks5://192.0.2.1:1080");
+ tor_free(uri);
+
+ /* Test with a SOCKS5 proxy, with username/password. */
+ options->Socks5ProxyUsername = tor_strdup("hwest");
+ options->Socks5ProxyPassword = tor_strdup("r34n1m470r");
+ uri = get_pt_proxy_uri();
+ tt_str_op(uri, ==, "socks5://hwest:r34n1m470r@192.0.2.1:1080");
+ tor_free(uri);
+ tor_free(options->Socks5Proxy);
+ tor_free(options->Socks5ProxyUsername);
+ tor_free(options->Socks5ProxyPassword);
+
+ /* Test with a HTTPS proxy, no authenticator. */
+ options->HTTPSProxy = tor_strdup("192.0.2.1:80");
+ ret = tor_addr_port_lookup(options->HTTPSProxy,
+ &options->HTTPSProxyAddr,
+ &options->HTTPSProxyPort);
+ tt_int_op(ret, ==, 0);
+ uri = get_pt_proxy_uri();
+ tt_str_op(uri, ==, "http://192.0.2.1:80");
+ tor_free(uri);
+
+ /* Test with a HTTPS proxy, with authenticator. */
+ options->HTTPSProxyAuthenticator = tor_strdup("hwest:r34n1m470r");
+ uri = get_pt_proxy_uri();
+ tt_str_op(uri, ==, "http://hwest:r34n1m470r@192.0.2.1:80");
+ tor_free(uri);
+ tor_free(options->HTTPSProxy);
+ tor_free(options->HTTPSProxyAuthenticator);
+
+ /* Token nod to the fact that IPv6 exists. */
+ options->Socks4Proxy = tor_strdup("[2001:db8::1]:1080");
+ ret = tor_addr_port_lookup(options->Socks4Proxy,
+ &options->Socks4ProxyAddr,
+ &options->Socks4ProxyPort);
+ tt_int_op(ret, ==, 0);
+ uri = get_pt_proxy_uri();
+ tt_str_op(uri, ==, "socks4a://[2001:db8::1]:1080");
+ tor_free(uri);
+ tor_free(options->Socks4Proxy);
+
+ done:
+ if (uri)
+ tor_free(uri);
+}
+
#define PT_LEGACY(name) \
- { #name, legacy_test_helper, 0, &legacy_setup, test_pt_ ## name }
+ { #name, test_pt_ ## name , 0, NULL, NULL }
struct testcase_t pt_tests[] = {
PT_LEGACY(parsing),
@@ -462,6 +542,8 @@ struct testcase_t pt_tests[] = {
NULL, NULL },
{ "configure_proxy",test_pt_configure_proxy, TT_FORK,
NULL, NULL },
+ { "get_pt_proxy_uri", test_get_pt_proxy_uri, TT_FORK,
+ NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_replay.c b/src/test/test_replay.c
index b48f582f5e..2f543512b0 100644
--- a/src/test/test_replay.c
+++ b/src/test/test_replay.c
@@ -18,12 +18,13 @@ static const char *test_buffer =
" mollit anim id est laborum.";
static void
-test_replaycache_alloc(void)
+test_replaycache_alloc(void *arg)
{
replaycache_t *r = NULL;
+ (void)arg;
r = replaycache_new(600, 300);
- test_assert(r != NULL);
+ tt_assert(r != NULL);
done:
if (r) replaycache_free(r);
@@ -32,21 +33,22 @@ test_replaycache_alloc(void)
}
static void
-test_replaycache_badalloc(void)
+test_replaycache_badalloc(void *arg)
{
replaycache_t *r = NULL;
/* Negative horizon should fail */
+ (void)arg;
r = replaycache_new(-600, 300);
- test_assert(r == NULL);
+ tt_assert(r == NULL);
/* Negative interval should get adjusted to zero */
r = replaycache_new(600, -300);
- test_assert(r != NULL);
- test_eq(r->scrub_interval, 0);
+ tt_assert(r != NULL);
+ tt_int_op(r->scrub_interval,==, 0);
replaycache_free(r);
/* Negative horizon and negative interval should still fail */
r = replaycache_new(-600, -300);
- test_assert(r == NULL);
+ tt_assert(r == NULL);
done:
if (r) replaycache_free(r);
@@ -55,35 +57,37 @@ test_replaycache_badalloc(void)
}
static void
-test_replaycache_free_null(void)
+test_replaycache_free_null(void *arg)
{
+ (void)arg;
replaycache_free(NULL);
/* Assert that we're here without horrible death */
- test_assert(1);
+ tt_assert(1);
done:
return;
}
static void
-test_replaycache_miss(void)
+test_replaycache_miss(void *arg)
{
replaycache_t *r = NULL;
int result;
+ (void)arg;
r = replaycache_new(600, 300);
- test_assert(r != NULL);
+ tt_assert(r != NULL);
result =
replaycache_add_and_test_internal(1200, r, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 0);
+ tt_int_op(result,==, 0);
/* poke the bad-parameter error case too */
result =
replaycache_add_and_test_internal(1200, NULL, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 0);
+ tt_int_op(result,==, 0);
done:
if (r) replaycache_free(r);
@@ -92,23 +96,24 @@ test_replaycache_miss(void)
}
static void
-test_replaycache_hit(void)
+test_replaycache_hit(void *arg)
{
replaycache_t *r = NULL;
int result;
+ (void)arg;
r = replaycache_new(600, 300);
- test_assert(r != NULL);
+ tt_assert(r != NULL);
result =
replaycache_add_and_test_internal(1200, r, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 0);
+ tt_int_op(result,==, 0);
result =
replaycache_add_and_test_internal(1300, r, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 1);
+ tt_int_op(result,==, 1);
done:
if (r) replaycache_free(r);
@@ -117,28 +122,29 @@ test_replaycache_hit(void)
}
static void
-test_replaycache_age(void)
+test_replaycache_age(void *arg)
{
replaycache_t *r = NULL;
int result;
+ (void)arg;
r = replaycache_new(600, 300);
- test_assert(r != NULL);
+ tt_assert(r != NULL);
result =
replaycache_add_and_test_internal(1200, r, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 0);
+ tt_int_op(result,==, 0);
result =
replaycache_add_and_test_internal(1300, r, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 1);
+ tt_int_op(result,==, 1);
result =
replaycache_add_and_test_internal(3000, r, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 0);
+ tt_int_op(result,==, 0);
done:
if (r) replaycache_free(r);
@@ -147,25 +153,26 @@ test_replaycache_age(void)
}
static void
-test_replaycache_elapsed(void)
+test_replaycache_elapsed(void *arg)
{
replaycache_t *r = NULL;
int result;
time_t elapsed;
+ (void)arg;
r = replaycache_new(600, 300);
- test_assert(r != NULL);
+ tt_assert(r != NULL);
result =
replaycache_add_and_test_internal(1200, r, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 0);
+ tt_int_op(result,==, 0);
result =
replaycache_add_and_test_internal(1300, r, test_buffer,
strlen(test_buffer), &elapsed);
- test_eq(result, 1);
- test_eq(elapsed, 100);
+ tt_int_op(result,==, 1);
+ tt_int_op(elapsed,==, 100);
done:
if (r) replaycache_free(r);
@@ -174,28 +181,29 @@ test_replaycache_elapsed(void)
}
static void
-test_replaycache_noexpire(void)
+test_replaycache_noexpire(void *arg)
{
replaycache_t *r = NULL;
int result;
+ (void)arg;
r = replaycache_new(0, 0);
- test_assert(r != NULL);
+ tt_assert(r != NULL);
result =
replaycache_add_and_test_internal(1200, r, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 0);
+ tt_int_op(result,==, 0);
result =
replaycache_add_and_test_internal(1300, r, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 1);
+ tt_int_op(result,==, 1);
result =
replaycache_add_and_test_internal(3000, r, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 1);
+ tt_int_op(result,==, 1);
done:
if (r) replaycache_free(r);
@@ -204,24 +212,25 @@ test_replaycache_noexpire(void)
}
static void
-test_replaycache_scrub(void)
+test_replaycache_scrub(void *arg)
{
replaycache_t *r = NULL;
int result;
+ (void)arg;
r = replaycache_new(600, 300);
- test_assert(r != NULL);
+ tt_assert(r != NULL);
/* Set up like in test_replaycache_hit() */
result =
replaycache_add_and_test_internal(100, r, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 0);
+ tt_int_op(result,==, 0);
result =
replaycache_add_and_test_internal(200, r, test_buffer,
strlen(test_buffer), NULL);
- test_eq(result, 1);
+ tt_int_op(result,==, 1);
/*
* Poke a few replaycache_scrub_if_needed_internal() error cases that
@@ -231,12 +240,12 @@ test_replaycache_scrub(void)
/* Null cache */
replaycache_scrub_if_needed_internal(300, NULL);
/* Assert we're still here */
- test_assert(1);
+ tt_assert(1);
/* Make sure we hit the aging-out case too */
replaycache_scrub_if_needed_internal(1500, r);
/* Assert that we aged it */
- test_eq(digestmap_size(r->digests_seen), 0);
+ tt_int_op(digestmap_size(r->digests_seen),==, 0);
done:
if (r) replaycache_free(r);
@@ -245,29 +254,30 @@ test_replaycache_scrub(void)
}
static void
-test_replaycache_future(void)
+test_replaycache_future(void *arg)
{
replaycache_t *r = NULL;
int result;
time_t elapsed = 0;
+ (void)arg;
r = replaycache_new(600, 300);
- test_assert(r != NULL);
+ tt_assert(r != NULL);
/* Set up like in test_replaycache_hit() */
result =
replaycache_add_and_test_internal(100, r, test_buffer,
strlen(test_buffer), &elapsed);
- test_eq(result, 0);
+ tt_int_op(result,==, 0);
/* elapsed should still be 0, since it wasn't written */
- test_eq(elapsed, 0);
+ tt_int_op(elapsed,==, 0);
result =
replaycache_add_and_test_internal(200, r, test_buffer,
strlen(test_buffer), &elapsed);
- test_eq(result, 1);
+ tt_int_op(result,==, 1);
/* elapsed should be the time since the last hit */
- test_eq(elapsed, 100);
+ tt_int_op(elapsed,==, 100);
/*
* Now let's turn the clock back to get coverage on the cache entry from the
@@ -277,9 +287,9 @@ test_replaycache_future(void)
replaycache_add_and_test_internal(150, r, test_buffer,
strlen(test_buffer), &elapsed);
/* We should still get a hit */
- test_eq(result, 1);
+ tt_int_op(result,==, 1);
/* ...but it shouldn't let us see a negative elapsed time */
- test_eq(elapsed, 0);
+ tt_int_op(elapsed,==, 0);
done:
if (r) replaycache_free(r);
@@ -288,7 +298,7 @@ test_replaycache_future(void)
}
static void
-test_replaycache_realtime(void)
+test_replaycache_realtime(void *arg)
{
replaycache_t *r = NULL;
/*
@@ -299,26 +309,27 @@ test_replaycache_realtime(void)
int result;
/* Test the realtime as well as *_internal() entry points */
+ (void)arg;
r = replaycache_new(600, 300);
- test_assert(r != NULL);
+ tt_assert(r != NULL);
/* This should miss */
result =
replaycache_add_and_test(r, test_buffer, strlen(test_buffer));
- test_eq(result, 0);
+ tt_int_op(result,==, 0);
/* This should hit */
result =
replaycache_add_and_test(r, test_buffer, strlen(test_buffer));
- test_eq(result, 1);
+ tt_int_op(result,==, 1);
/* This should hit and return a small elapsed time */
result =
replaycache_add_test_and_elapsed(r, test_buffer,
strlen(test_buffer), &elapsed);
- test_eq(result, 1);
- test_assert(elapsed >= 0);
- test_assert(elapsed <= 5);
+ tt_int_op(result,==, 1);
+ tt_assert(elapsed >= 0);
+ tt_assert(elapsed <= 5);
/* Scrub it to exercise that entry point too */
replaycache_scrub_if_needed(r);
@@ -329,7 +340,7 @@ test_replaycache_realtime(void)
}
#define REPLAYCACHE_LEGACY(name) \
- { #name, legacy_test_helper, 0, &legacy_setup, test_replaycache_ ## name }
+ { #name, test_replaycache_ ## name , 0, NULL, NULL }
struct testcase_t replaycache_tests[] = {
REPLAYCACHE_LEGACY(alloc),
diff --git a/src/test/test_routerset.c b/src/test/test_routerset.c
index 0ea1ef2d89..81e4dbb1eb 100644
--- a/src/test/test_routerset.c
+++ b/src/test/test_routerset.c
@@ -775,10 +775,11 @@ NS(test_main)(void *arg)
{
routerset_t *set = routerset_new();
int contains;
+ uint8_t foo[20] = { 2, 3, 4 };
(void)arg;
- digestmap_set(set->digests, "foo", (void *)1);
- contains = routerset_contains(set, NULL, 0, NULL, "foo", 0);
+ digestmap_set(set->digests, (const char*)foo, (void *)1);
+ contains = routerset_contains(set, NULL, 0, NULL, (const char*)foo, 0);
routerset_free(set);
tt_int_op(contains, ==, 4);
@@ -799,10 +800,12 @@ NS(test_main)(void *arg)
{
routerset_t *set = routerset_new();
int contains;
+ uint8_t bar[20] = { 9, 10, 11, 55 };
+ uint8_t foo[20] = { 1, 2, 3, 4};
(void)arg;
- digestmap_set(set->digests, "bar", (void *)1);
- contains = routerset_contains(set, NULL, 0, NULL, "foo", 0);
+ digestmap_set(set->digests, (const char*)bar, (void *)1);
+ contains = routerset_contains(set, NULL, 0, NULL, (const char*)foo, 0);
routerset_free(set);
tt_int_op(contains, ==, 0);
@@ -823,9 +826,10 @@ NS(test_main)(void *arg)
{
routerset_t *set = routerset_new();
int contains;
+ uint8_t bar[20] = { 9, 10, 11, 55 };
(void)arg;
- digestmap_set(set->digests, "bar", (void *)1);
+ digestmap_set(set->digests, (const char*)bar, (void *)1);
contains = routerset_contains(set, NULL, 0, NULL, NULL, 0);
routerset_free(set);
diff --git a/src/test/test_socks.c b/src/test/test_socks.c
index 4ce61e068b..9aaa16e081 100644
--- a/src/test/test_socks.c
+++ b/src/test/test_socks.c
@@ -61,10 +61,10 @@ test_socks_4_unsupported_commands(void *ptr)
/* SOCKS 4 Send BIND [02] to IP address 2.2.2.2:4369 */
ADD_DATA(buf, "\x04\x02\x11\x11\x02\x02\x02\x02\x00");
- test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
get_options()->SafeSocks) == -1);
- test_eq(4, socks->socks_version);
- test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */
+ tt_int_op(4,==, socks->socks_version);
+ tt_int_op(0,==, socks->replylen); /* XXX: shouldn't tor reply? */
done:
;
@@ -76,49 +76,49 @@ test_socks_4_supported_commands(void *ptr)
{
SOCKS_TEST_INIT();
- test_eq(0, buf_datalen(buf));
+ tt_int_op(0,==, buf_datalen(buf));
/* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4370 */
ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x03\x00");
- test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
get_options()->SafeSocks) == 1);
- test_eq(4, socks->socks_version);
- test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */
- test_eq(SOCKS_COMMAND_CONNECT, socks->command);
- test_streq("2.2.2.3", socks->address);
- test_eq(4370, socks->port);
- test_assert(socks->got_auth == 0);
- test_assert(! socks->username);
-
- test_eq(0, buf_datalen(buf));
+ tt_int_op(4,==, socks->socks_version);
+ tt_int_op(0,==, socks->replylen); /* XXX: shouldn't tor reply? */
+ tt_int_op(SOCKS_COMMAND_CONNECT,==, socks->command);
+ tt_str_op("2.2.2.3",==, socks->address);
+ tt_int_op(4370,==, socks->port);
+ tt_assert(socks->got_auth == 0);
+ tt_assert(! socks->username);
+
+ tt_int_op(0,==, buf_datalen(buf));
socks_request_clear(socks);
/* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4369 with userid*/
ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x04me\x00");
- test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
get_options()->SafeSocks) == 1);
- test_eq(4, socks->socks_version);
- test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */
- test_eq(SOCKS_COMMAND_CONNECT, socks->command);
- test_streq("2.2.2.4", socks->address);
- test_eq(4370, socks->port);
- test_assert(socks->got_auth == 1);
- test_assert(socks->username);
- test_eq(2, socks->usernamelen);
- test_memeq("me", socks->username, 2);
-
- test_eq(0, buf_datalen(buf));
+ tt_int_op(4,==, socks->socks_version);
+ tt_int_op(0,==, socks->replylen); /* XXX: shouldn't tor reply? */
+ tt_int_op(SOCKS_COMMAND_CONNECT,==, socks->command);
+ tt_str_op("2.2.2.4",==, socks->address);
+ tt_int_op(4370,==, socks->port);
+ tt_assert(socks->got_auth == 1);
+ tt_assert(socks->username);
+ tt_int_op(2,==, socks->usernamelen);
+ tt_mem_op("me",==, socks->username, 2);
+
+ tt_int_op(0,==, buf_datalen(buf));
socks_request_clear(socks);
/* SOCKS 4a Send RESOLVE [F0] request for torproject.org */
ADD_DATA(buf, "\x04\xF0\x01\x01\x00\x00\x00\x02me\x00torproject.org\x00");
- test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
get_options()->SafeSocks) == 1);
- test_eq(4, socks->socks_version);
- test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */
- test_streq("torproject.org", socks->address);
+ tt_int_op(4,==, socks->socks_version);
+ tt_int_op(0,==, socks->replylen); /* XXX: shouldn't tor reply? */
+ tt_str_op("torproject.org",==, socks->address);
- test_eq(0, buf_datalen(buf));
+ tt_int_op(0,==, buf_datalen(buf));
done:
;
@@ -133,33 +133,43 @@ test_socks_5_unsupported_commands(void *ptr)
/* SOCKS 5 Send unsupported BIND [02] command */
ADD_DATA(buf, "\x05\x02\x00\x01");
- test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
- get_options()->SafeSocks), 0);
- test_eq(0, buf_datalen(buf));
- test_eq(5, socks->socks_version);
- test_eq(2, socks->replylen);
- test_eq(5, socks->reply[0]);
- test_eq(0, socks->reply[1]);
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),==, 0);
+ tt_int_op(0,==, buf_datalen(buf));
+ tt_int_op(5,==, socks->socks_version);
+ tt_int_op(2,==, socks->replylen);
+ tt_int_op(5,==, socks->reply[0]);
+ tt_int_op(0,==, socks->reply[1]);
ADD_DATA(buf, "\x05\x02\x00\x01\x02\x02\x02\x01\x01\x01");
- test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
- get_options()->SafeSocks), -1);
- /* XXX: shouldn't tor reply 'command not supported' [07]? */
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),==, -1);
+
+ tt_int_op(5,==,socks->socks_version);
+ tt_int_op(10,==,socks->replylen);
+ tt_int_op(5,==,socks->reply[0]);
+ tt_int_op(SOCKS5_COMMAND_NOT_SUPPORTED,==,socks->reply[1]);
+ tt_int_op(1,==,socks->reply[3]);
buf_clear(buf);
socks_request_clear(socks);
/* SOCKS 5 Send unsupported UDP_ASSOCIATE [03] command */
- ADD_DATA(buf, "\x05\x03\x00\x01\x02");
- test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
- get_options()->SafeSocks), 0);
- test_eq(5, socks->socks_version);
- test_eq(2, socks->replylen);
- test_eq(5, socks->reply[0]);
- test_eq(2, socks->reply[1]);
+ ADD_DATA(buf, "\x05\x02\x00\x01");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),==, 0);
+ tt_int_op(5,==, socks->socks_version);
+ tt_int_op(2,==, socks->replylen);
+ tt_int_op(5,==, socks->reply[0]);
+ tt_int_op(0,==, socks->reply[1]);
ADD_DATA(buf, "\x05\x03\x00\x01\x02\x02\x02\x01\x01\x01");
- test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
- get_options()->SafeSocks), -1);
- /* XXX: shouldn't tor reply 'command not supported' [07]? */
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),==, -1);
+
+ tt_int_op(5,==,socks->socks_version);
+ tt_int_op(10,==,socks->replylen);
+ tt_int_op(5,==,socks->reply[0]);
+ tt_int_op(SOCKS5_COMMAND_NOT_SUPPORTED,==,socks->reply[1]);
+ tt_int_op(1,==,socks->reply[3]);
done:
;
@@ -173,64 +183,64 @@ test_socks_5_supported_commands(void *ptr)
/* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */
ADD_DATA(buf, "\x05\x01\x00");
- test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
- get_options()->SafeSocks), 0);
- test_eq(5, socks->socks_version);
- test_eq(2, socks->replylen);
- test_eq(5, socks->reply[0]);
- test_eq(0, socks->reply[1]);
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),==, 0);
+ tt_int_op(5,==, socks->socks_version);
+ tt_int_op(2,==, socks->replylen);
+ tt_int_op(5,==, socks->reply[0]);
+ tt_int_op(0,==, socks->reply[1]);
ADD_DATA(buf, "\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11");
- test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
- get_options()->SafeSocks), 1);
- test_streq("2.2.2.2", socks->address);
- test_eq(4369, socks->port);
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),==, 1);
+ tt_str_op("2.2.2.2",==, socks->address);
+ tt_int_op(4369,==, socks->port);
- test_eq(0, buf_datalen(buf));
+ tt_int_op(0,==, buf_datalen(buf));
socks_request_clear(socks);
/* SOCKS 5 Send CONNECT [01] to FQDN torproject.org:4369 */
ADD_DATA(buf, "\x05\x01\x00");
ADD_DATA(buf, "\x05\x01\x00\x03\x0Etorproject.org\x11\x11");
- test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
- get_options()->SafeSocks), 1);
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),==, 1);
- test_eq(5, socks->socks_version);
- test_eq(2, socks->replylen);
- test_eq(5, socks->reply[0]);
- test_eq(0, socks->reply[1]);
- test_streq("torproject.org", socks->address);
- test_eq(4369, socks->port);
+ tt_int_op(5,==, socks->socks_version);
+ tt_int_op(2,==, socks->replylen);
+ tt_int_op(5,==, socks->reply[0]);
+ tt_int_op(0,==, socks->reply[1]);
+ tt_str_op("torproject.org",==, socks->address);
+ tt_int_op(4369,==, socks->port);
- test_eq(0, buf_datalen(buf));
+ tt_int_op(0,==, buf_datalen(buf));
socks_request_clear(socks);
/* SOCKS 5 Send RESOLVE [F0] request for torproject.org:4369 */
ADD_DATA(buf, "\x05\x01\x00");
ADD_DATA(buf, "\x05\xF0\x00\x03\x0Etorproject.org\x01\x02");
- test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
get_options()->SafeSocks) == 1);
- test_eq(5, socks->socks_version);
- test_eq(2, socks->replylen);
- test_eq(5, socks->reply[0]);
- test_eq(0, socks->reply[1]);
- test_streq("torproject.org", socks->address);
+ tt_int_op(5,==, socks->socks_version);
+ tt_int_op(2,==, socks->replylen);
+ tt_int_op(5,==, socks->reply[0]);
+ tt_int_op(0,==, socks->reply[1]);
+ tt_str_op("torproject.org",==, socks->address);
- test_eq(0, buf_datalen(buf));
+ tt_int_op(0,==, buf_datalen(buf));
socks_request_clear(socks);
/* SOCKS 5 Send RESOLVE_PTR [F1] for IP address 2.2.2.5 */
ADD_DATA(buf, "\x05\x01\x00");
ADD_DATA(buf, "\x05\xF1\x00\x01\x02\x02\x02\x05\x01\x03");
- test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ tt_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
get_options()->SafeSocks) == 1);
- test_eq(5, socks->socks_version);
- test_eq(2, socks->replylen);
- test_eq(5, socks->reply[0]);
- test_eq(0, socks->reply[1]);
- test_streq("2.2.2.5", socks->address);
+ tt_int_op(5,==, socks->socks_version);
+ tt_int_op(2,==, socks->replylen);
+ tt_int_op(5,==, socks->reply[0]);
+ tt_int_op(0,==, socks->reply[1]);
+ tt_str_op("2.2.2.5",==, socks->address);
- test_eq(0, buf_datalen(buf));
+ tt_int_op(0,==, buf_datalen(buf));
done:
;
@@ -244,30 +254,30 @@ test_socks_5_no_authenticate(void *ptr)
/*SOCKS 5 No Authentication */
ADD_DATA(buf,"\x05\x01\x00");
- test_assert(!fetch_from_buf_socks(buf, socks,
+ tt_assert(!fetch_from_buf_socks(buf, socks,
get_options()->TestSocks,
get_options()->SafeSocks));
- test_eq(2, socks->replylen);
- test_eq(5, socks->reply[0]);
- test_eq(SOCKS_NO_AUTH, socks->reply[1]);
+ tt_int_op(2,==, socks->replylen);
+ tt_int_op(5,==, socks->reply[0]);
+ tt_int_op(SOCKS_NO_AUTH,==, socks->reply[1]);
- test_eq(0, buf_datalen(buf));
+ tt_int_op(0,==, buf_datalen(buf));
/*SOCKS 5 Send username/password anyway - pretend to be broken */
ADD_DATA(buf,"\x01\x02\x01\x01\x02\x01\x01");
- test_assert(!fetch_from_buf_socks(buf, socks,
+ tt_assert(!fetch_from_buf_socks(buf, socks,
get_options()->TestSocks,
get_options()->SafeSocks));
- test_eq(5, socks->socks_version);
- test_eq(2, socks->replylen);
- test_eq(1, socks->reply[0]);
- test_eq(0, socks->reply[1]);
+ tt_int_op(5,==, socks->socks_version);
+ tt_int_op(2,==, socks->replylen);
+ tt_int_op(1,==, socks->reply[0]);
+ tt_int_op(0,==, socks->reply[1]);
- test_eq(2, socks->usernamelen);
- test_eq(2, socks->passwordlen);
+ tt_int_op(2,==, socks->usernamelen);
+ tt_int_op(2,==, socks->passwordlen);
- test_memeq("\x01\x01", socks->username, 2);
- test_memeq("\x01\x01", socks->password, 2);
+ tt_mem_op("\x01\x01",==, socks->username, 2);
+ tt_mem_op("\x01\x01",==, socks->password, 2);
done:
;
@@ -282,31 +292,31 @@ test_socks_5_authenticate(void *ptr)
/* SOCKS 5 Negotiate username/password authentication */
ADD_DATA(buf, "\x05\x01\x02");
- test_assert(!fetch_from_buf_socks(buf, socks,
+ tt_assert(!fetch_from_buf_socks(buf, socks,
get_options()->TestSocks,
get_options()->SafeSocks));
- test_eq(2, socks->replylen);
- test_eq(5, socks->reply[0]);
- test_eq(SOCKS_USER_PASS, socks->reply[1]);
- test_eq(5, socks->socks_version);
+ tt_int_op(2,==, socks->replylen);
+ tt_int_op(5,==, socks->reply[0]);
+ tt_int_op(SOCKS_USER_PASS,==, socks->reply[1]);
+ tt_int_op(5,==, socks->socks_version);
- test_eq(0, buf_datalen(buf));
+ tt_int_op(0,==, buf_datalen(buf));
/* SOCKS 5 Send username/password */
ADD_DATA(buf, "\x01\x02me\x08mypasswd");
- test_assert(!fetch_from_buf_socks(buf, socks,
+ tt_assert(!fetch_from_buf_socks(buf, socks,
get_options()->TestSocks,
get_options()->SafeSocks));
- test_eq(5, socks->socks_version);
- test_eq(2, socks->replylen);
- test_eq(1, socks->reply[0]);
- test_eq(0, socks->reply[1]);
+ tt_int_op(5,==, socks->socks_version);
+ tt_int_op(2,==, socks->replylen);
+ tt_int_op(1,==, socks->reply[0]);
+ tt_int_op(0,==, socks->reply[1]);
- test_eq(2, socks->usernamelen);
- test_eq(8, socks->passwordlen);
+ tt_int_op(2,==, socks->usernamelen);
+ tt_int_op(8,==, socks->passwordlen);
- test_memeq("me", socks->username, 2);
- test_memeq("mypasswd", socks->password, 8);
+ tt_mem_op("me",==, socks->username, 2);
+ tt_mem_op("mypasswd",==, socks->password, 8);
done:
;
@@ -321,34 +331,34 @@ test_socks_5_authenticate_with_data(void *ptr)
/* SOCKS 5 Negotiate username/password authentication */
ADD_DATA(buf, "\x05\x01\x02");
- test_assert(!fetch_from_buf_socks(buf, socks,
+ tt_assert(!fetch_from_buf_socks(buf, socks,
get_options()->TestSocks,
get_options()->SafeSocks));
- test_eq(2, socks->replylen);
- test_eq(5, socks->reply[0]);
- test_eq(SOCKS_USER_PASS, socks->reply[1]);
- test_eq(5, socks->socks_version);
+ tt_int_op(2,==, socks->replylen);
+ tt_int_op(5,==, socks->reply[0]);
+ tt_int_op(SOCKS_USER_PASS,==, socks->reply[1]);
+ tt_int_op(5,==, socks->socks_version);
- test_eq(0, buf_datalen(buf));
+ tt_int_op(0,==, buf_datalen(buf));
/* SOCKS 5 Send username/password */
/* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */
ADD_DATA(buf, "\x01\x02me\x03you\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11");
- test_assert(fetch_from_buf_socks(buf, socks,
+ tt_assert(fetch_from_buf_socks(buf, socks,
get_options()->TestSocks,
get_options()->SafeSocks) == 1);
- test_eq(5, socks->socks_version);
- test_eq(2, socks->replylen);
- test_eq(1, socks->reply[0]);
- test_eq(0, socks->reply[1]);
+ tt_int_op(5,==, socks->socks_version);
+ tt_int_op(2,==, socks->replylen);
+ tt_int_op(1,==, socks->reply[0]);
+ tt_int_op(0,==, socks->reply[1]);
- test_streq("2.2.2.2", socks->address);
- test_eq(4369, socks->port);
+ tt_str_op("2.2.2.2",==, socks->address);
+ tt_int_op(4369,==, socks->port);
- test_eq(2, socks->usernamelen);
- test_eq(3, socks->passwordlen);
- test_memeq("me", socks->username, 2);
- test_memeq("you", socks->password, 3);
+ tt_int_op(2,==, socks->usernamelen);
+ tt_int_op(3,==, socks->passwordlen);
+ tt_mem_op("me",==, socks->username, 2);
+ tt_mem_op("you",==, socks->password, 3);
done:
;
@@ -362,13 +372,84 @@ test_socks_5_auth_before_negotiation(void *ptr)
/* SOCKS 5 Send username/password */
ADD_DATA(buf, "\x01\x02me\x02me");
- test_assert(fetch_from_buf_socks(buf, socks,
+ tt_assert(fetch_from_buf_socks(buf, socks,
get_options()->TestSocks,
get_options()->SafeSocks) == -1);
- test_eq(0, socks->socks_version);
- test_eq(0, socks->replylen);
- test_eq(0, socks->reply[0]);
- test_eq(0, socks->reply[1]);
+ tt_int_op(0,==, socks->socks_version);
+ tt_int_op(0,==, socks->replylen);
+ tt_int_op(0,==, socks->reply[0]);
+ tt_int_op(0,==, socks->reply[1]);
+
+ done:
+ ;
+}
+
+/** Perform malformed SOCKS 5 commands */
+static void
+test_socks_5_malformed_commands(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* XXX: Stringified address length > MAX_SOCKS_ADDR_LEN will never happen */
+
+ /* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369, with SafeSocks set */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, 1),==,
+ -1);
+
+ tt_int_op(5,==,socks->socks_version);
+ tt_int_op(10,==,socks->replylen);
+ tt_int_op(5,==,socks->reply[0]);
+ tt_int_op(SOCKS5_NOT_ALLOWED,==,socks->reply[1]);
+ tt_int_op(1,==,socks->reply[3]);
+
+ buf_clear(buf);
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send RESOLVE_PTR [F1] for FQDN torproject.org */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\xF1\x00\x03\x0Etorproject.org\x11\x11");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),==, -1);
+
+ tt_int_op(5,==,socks->socks_version);
+ tt_int_op(10,==,socks->replylen);
+ tt_int_op(5,==,socks->reply[0]);
+ tt_int_op(SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED,==,socks->reply[1]);
+ tt_int_op(1,==,socks->reply[3]);
+
+ buf_clear(buf);
+ socks_request_clear(socks);
+
+ /* XXX: len + 1 > MAX_SOCKS_ADDR_LEN (FQDN request) will never happen */
+
+ /* SOCKS 5 Send CONNECT [01] to FQDN """"".com */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\x01\x00\x03\x09\"\"\"\"\".com\x11\x11");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),==, -1);
+
+ tt_int_op(5,==,socks->socks_version);
+ tt_int_op(10,==,socks->replylen);
+ tt_int_op(5,==,socks->reply[0]);
+ tt_int_op(SOCKS5_GENERAL_ERROR,==,socks->reply[1]);
+ tt_int_op(1,==,socks->reply[3]);
+
+ buf_clear(buf);
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send CONNECT [01] to address type 0x23 */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\x01\x00\x23\x02\x02\x02\x02\x11\x11");
+ tt_int_op(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks),==, -1);
+
+ tt_int_op(5,==,socks->socks_version);
+ tt_int_op(10,==,socks->replylen);
+ tt_int_op(5,==,socks->reply[0]);
+ tt_int_op(SOCKS5_ADDRESS_TYPE_NOT_SUPPORTED,==,socks->reply[1]);
+ tt_int_op(1,==,socks->reply[3]);
done:
;
@@ -387,6 +468,7 @@ struct testcase_t socks_tests[] = {
SOCKSENT(5_auth_before_negotiation),
SOCKSENT(5_authenticate),
SOCKSENT(5_authenticate_with_data),
+ SOCKSENT(5_malformed_commands),
END_OF_TESTCASES
};
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 1b7c936fd7..e1f77b9636 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -22,6 +22,7 @@
#include <tchar.h>
#endif
#include <math.h>
+#include <ctype.h>
/* XXXX this is a minimal wrapper to make the unit tests compile with the
* changed tor_timegm interface. */
@@ -64,8 +65,8 @@ test_util_read_until_eof_impl(const char *fname, size_t file_len,
else
tt_int_op(sz, ==, file_len);
- test_mem_op(test_str, ==, str, sz);
- test_assert(str[sz] == '\0');
+ tt_mem_op(test_str, ==, str, sz);
+ tt_int_op(str[sz], ==, '\0');
done:
unlink(fifo_name);
@@ -177,7 +178,7 @@ test_util_write_chunks_to_file(void *arg)
str = read_file_to_str(fname, RFTS_BIN, &st);
tt_assert(str != NULL);
tt_u64_op((uint64_t)st.st_size, ==, data_str_len);
- test_mem_op(data_str, ==, str, data_str_len);
+ tt_mem_op(data_str, ==, str, data_str_len);
tor_free(str);
// assert that the tempfile is removed (should not leave artifacts)
@@ -208,14 +209,14 @@ test_util_write_chunks_to_file(void *arg)
str = read_file_to_str(fname, RFTS_BIN, &st);
tt_assert(str != NULL);
tt_u64_op((uint64_t)st.st_size, ==, data_str_len);
- test_mem_op(data_str, ==, str, data_str_len);
+ tt_mem_op(data_str, ==, str, data_str_len);
tor_free(str);
// assert the tempfile still contains the known string
str = read_file_to_str(tempname, RFTS_BIN, &st);
tt_assert(str != NULL);
tt_u64_op((uint64_t)st.st_size, ==, temp_str_len);
- test_mem_op(temp_str, ==, str, temp_str_len);
+ tt_mem_op(temp_str, ==, str, temp_str_len);
done:
unlink(fname);
@@ -228,11 +229,24 @@ test_util_write_chunks_to_file(void *arg)
tor_free(temp_str);
}
+#define _TFE(a, b, f) tt_int_op((a).f, ==, (b).f)
+/** test the minimum set of struct tm fields needed for a unique epoch value
+ * this is also the set we use to test tor_timegm */
+#define TM_EQUAL(a, b) \
+ TT_STMT_BEGIN \
+ _TFE(a, b, tm_year); \
+ _TFE(a, b, tm_mon ); \
+ _TFE(a, b, tm_mday); \
+ _TFE(a, b, tm_hour); \
+ _TFE(a, b, tm_min ); \
+ _TFE(a, b, tm_sec ); \
+ TT_STMT_END
+
static void
-test_util_time(void)
+test_util_time(void *arg)
{
struct timeval start, end;
- struct tm a_time;
+ struct tm a_time, b_time;
char timestr[128];
time_t t_res;
int i;
@@ -240,117 +254,343 @@ test_util_time(void)
/* Test tv_udiff */
+ (void)arg;
start.tv_sec = 5;
start.tv_usec = 5000;
end.tv_sec = 5;
end.tv_usec = 5000;
- test_eq(0L, tv_udiff(&start, &end));
+ tt_int_op(0L,==, tv_udiff(&start, &end));
end.tv_usec = 7000;
- test_eq(2000L, tv_udiff(&start, &end));
+ tt_int_op(2000L,==, tv_udiff(&start, &end));
end.tv_sec = 6;
- test_eq(1002000L, tv_udiff(&start, &end));
+ tt_int_op(1002000L,==, tv_udiff(&start, &end));
end.tv_usec = 0;
- test_eq(995000L, tv_udiff(&start, &end));
+ tt_int_op(995000L,==, tv_udiff(&start, &end));
end.tv_sec = 4;
- test_eq(-1005000L, tv_udiff(&start, &end));
+ tt_int_op(-1005000L,==, tv_udiff(&start, &end));
- /* Test tor_timegm */
+ /* Test tor_timegm & tor_gmtime_r */
/* The test values here are confirmed to be correct on a platform
- * with a working timegm. */
+ * with a working timegm & gmtime_r. */
+
+ /* Start with known-zero a_time and b_time.
+ * This avoids passing uninitialised values to TM_EQUAL in a_time.
+ * Zeroing may not be needed for b_time, as long as tor_gmtime_r
+ * never reads the existing values in the structure.
+ * But we really don't want intermittently failing tests. */
+ memset(&a_time, 0, sizeof(struct tm));
+ memset(&b_time, 0, sizeof(struct tm));
+
a_time.tm_year = 2003-1900;
a_time.tm_mon = 7;
a_time.tm_mday = 30;
a_time.tm_hour = 6;
a_time.tm_min = 14;
a_time.tm_sec = 55;
- test_eq((time_t) 1062224095UL, tor_timegm(&a_time));
+ t_res = 1062224095UL;
+ tt_int_op(t_res, ==, tor_timegm(&a_time));
+ tor_gmtime_r(&t_res, &b_time);
+ TM_EQUAL(a_time, b_time);
+
a_time.tm_year = 2004-1900; /* Try a leap year, after feb. */
- test_eq((time_t) 1093846495UL, tor_timegm(&a_time));
+ t_res = 1093846495UL;
+ tt_int_op(t_res, ==, tor_timegm(&a_time));
+ tor_gmtime_r(&t_res, &b_time);
+ TM_EQUAL(a_time, b_time);
+
a_time.tm_mon = 1; /* Try a leap year, in feb. */
a_time.tm_mday = 10;
- test_eq((time_t) 1076393695UL, tor_timegm(&a_time));
+ t_res = 1076393695UL;
+ tt_int_op(t_res, ==, tor_timegm(&a_time));
+ tor_gmtime_r(&t_res, &b_time);
+ TM_EQUAL(a_time, b_time);
+
a_time.tm_mon = 0;
- a_time.tm_mday = 10;
- test_eq((time_t) 1073715295UL, tor_timegm(&a_time));
+ t_res = 1073715295UL;
+ tt_int_op(t_res, ==, tor_timegm(&a_time));
+ tor_gmtime_r(&t_res, &b_time);
+ TM_EQUAL(a_time, b_time);
+
+ /* Test tor_timegm out of range */
+
+ /* year */
+
+ /* Wrong year < 1970 */
+ a_time.tm_year = 1969-1900;
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_year = -1-1900;
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+#if SIZEOF_INT == 4 || SIZEOF_INT == 8
+ a_time.tm_year = -1*(1 << 16);
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ /* one of the smallest tm_year values my 64 bit system supports:
+ * t_res = -9223372036854775LL without clamping */
+ a_time.tm_year = -292275055-1900;
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_year = INT32_MIN;
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+#endif
+
+#if SIZEOF_INT == 8
+ a_time.tm_year = -1*(1 << 48);
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ /* while unlikely, the system's gmtime(_r) could return
+ * a "correct" retrospective gregorian negative year value,
+ * which I'm pretty sure is:
+ * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
+ * 730485 is the number of days in two millenia, including leap days */
+ a_time.tm_year = -292277022657-1900;
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_year = INT64_MIN;
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+#endif
+
+ /* Wrong year >= INT32_MAX - 1900 */
+#if SIZEOF_INT == 4 || SIZEOF_INT == 8
+ a_time.tm_year = INT32_MAX-1900;
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_year = INT32_MAX;
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+#endif
+
+#if SIZEOF_INT == 8
+ /* one of the largest tm_year values my 64 bit system supports */
+ a_time.tm_year = 292278994-1900;
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ /* while unlikely, the system's gmtime(_r) could return
+ * a "correct" proleptic gregorian year value,
+ * which I'm pretty sure is:
+ * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
+ * 730485 is the number of days in two millenia, including leap days */
+ a_time.tm_year = 292277026596-1900;
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_year = INT64_MAX-1900;
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_year = INT64_MAX;
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+#endif
+
+ /* month */
+ a_time.tm_year = 2007-1900; /* restore valid year */
+
a_time.tm_mon = 12; /* Wrong month, it's 0-based */
- a_time.tm_mday = 10;
- test_eq((time_t) -1, tor_timegm(&a_time));
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
a_time.tm_mon = -1; /* Wrong month */
- a_time.tm_mday = 10;
- test_eq((time_t) -1, tor_timegm(&a_time));
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ /* day */
+ a_time.tm_mon = 6; /* Try July */
+ a_time.tm_mday = 32; /* Wrong day */
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_mon = 5; /* Try June */
+ a_time.tm_mday = 31; /* Wrong day */
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_year = 2008-1900; /* Try a leap year */
+ a_time.tm_mon = 1; /* in feb. */
+ a_time.tm_mday = 30; /* Wrong day */
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_year = 2011-1900; /* Try a non-leap year */
+ a_time.tm_mon = 1; /* in feb. */
+ a_time.tm_mday = 29; /* Wrong day */
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_mday = 0; /* Wrong day, it's 1-based (to be different) */
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ /* hour */
+ a_time.tm_mday = 3; /* restore valid month day */
+
+ a_time.tm_hour = 24; /* Wrong hour, it's 0-based */
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_hour = -1; /* Wrong hour */
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ /* minute */
+ a_time.tm_hour = 22; /* restore valid hour */
+
+ a_time.tm_min = 60; /* Wrong minute, it's 0-based */
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_min = -1; /* Wrong minute */
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ /* second */
+ a_time.tm_min = 37; /* restore valid minute */
+
+ a_time.tm_sec = 61; /* Wrong second: 0-based with leap seconds */
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ a_time.tm_sec = -1; /* Wrong second */
+ tt_int_op((time_t) -1,==, tor_timegm(&a_time));
+
+ /* Test tor_gmtime_r out of range */
+
+ /* time_t < 0 yields a year clamped to 1 or 1970,
+ * depending on whether the implementation of the system gmtime(_r)
+ * sets struct tm (1) or not (1970) */
+ t_res = -1;
+ tor_gmtime_r(&t_res, &b_time);
+ tt_assert(b_time.tm_year == (1970-1900) ||
+ b_time.tm_year == (1969-1900));
+
+ if (sizeof(time_t) == 4 || sizeof(time_t) == 8) {
+ t_res = -1*(1 << 30);
+ tor_gmtime_r(&t_res, &b_time);
+ tt_assert(b_time.tm_year == (1970-1900) ||
+ b_time.tm_year == (1935-1900));
+
+ t_res = INT32_MIN;
+ tor_gmtime_r(&t_res, &b_time);
+ tt_assert(b_time.tm_year == (1970-1900) ||
+ b_time.tm_year == (1901-1900));
+ }
+
+ if (sizeof(time_t) == 8) {
+ /* one of the smallest tm_year values my 64 bit system supports:
+ * b_time.tm_year == (-292275055LL-1900LL) without clamping */
+ t_res = -9223372036854775LL;
+ tor_gmtime_r(&t_res, &b_time);
+ tt_assert(b_time.tm_year == (1970-1900) ||
+ b_time.tm_year == (1-1900));
+
+ /* while unlikely, the system's gmtime(_r) could return
+ * a "correct" retrospective gregorian negative year value,
+ * which I'm pretty sure is:
+ * -1*(2^63)/60/60/24*2000/730485 + 1970 = -292277022657
+ * 730485 is the number of days in two millenia, including leap days
+ * (int64_t)b_time.tm_year == (-292277022657LL-1900LL) without clamping */
+ t_res = INT64_MIN;
+ tor_gmtime_r(&t_res, &b_time);
+ tt_assert(b_time.tm_year == (1970-1900) ||
+ b_time.tm_year == (1-1900));
+ }
+
+ /* time_t >= INT_MAX yields a year clamped to 2037 or 9999,
+ * depending on whether the implementation of the system gmtime(_r)
+ * sets struct tm (9999) or not (2037) */
+ if (sizeof(time_t) == 4 || sizeof(time_t) == 8) {
+ t_res = 3*(1 << 29);
+ tor_gmtime_r(&t_res, &b_time);
+ tt_assert(b_time.tm_year == (2021-1900));
+
+ t_res = INT32_MAX;
+ tor_gmtime_r(&t_res, &b_time);
+ tt_assert(b_time.tm_year == (2037-1900) ||
+ b_time.tm_year == (2038-1900));
+ }
+
+ if (sizeof(time_t) == 8) {
+ /* one of the largest tm_year values my 64 bit system supports:
+ * b_time.tm_year == (292278994L-1900L) without clamping */
+ t_res = 9223372036854775LL;
+ tor_gmtime_r(&t_res, &b_time);
+ tt_assert(b_time.tm_year == (2037-1900) ||
+ b_time.tm_year == (9999-1900));
+
+ /* while unlikely, the system's gmtime(_r) could return
+ * a "correct" proleptic gregorian year value,
+ * which I'm pretty sure is:
+ * (2^63-1)/60/60/24*2000/730485 + 1970 = 292277026596
+ * 730485 is the number of days in two millenia, including leap days
+ * (int64_t)b_time.tm_year == (292277026596L-1900L) without clamping */
+ t_res = INT64_MAX;
+ tor_gmtime_r(&t_res, &b_time);
+ tt_assert(b_time.tm_year == (2037-1900) ||
+ b_time.tm_year == (9999-1900));
+ }
/* Test {format,parse}_rfc1123_time */
format_rfc1123_time(timestr, 0);
- test_streq("Thu, 01 Jan 1970 00:00:00 GMT", timestr);
+ tt_str_op("Thu, 01 Jan 1970 00:00:00 GMT",==, timestr);
format_rfc1123_time(timestr, (time_t)1091580502UL);
- test_streq("Wed, 04 Aug 2004 00:48:22 GMT", timestr);
+ tt_str_op("Wed, 04 Aug 2004 00:48:22 GMT",==, timestr);
t_res = 0;
i = parse_rfc1123_time(timestr, &t_res);
- test_eq(0,i);
- test_eq(t_res, (time_t)1091580502UL);
+ tt_int_op(0,==, i);
+ tt_int_op(t_res,==, (time_t)1091580502UL);
/* The timezone doesn't matter */
t_res = 0;
- test_eq(0, parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res));
- test_eq(t_res, (time_t)1091580502UL);
- test_eq(-1, parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res));
- test_eq(-1, parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res));
- test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res));
- test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res));
- test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res));
- test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res));
- test_eq(-1, parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res));
- test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res));
-
-#if 0
- /* This fails, I imagine it's important and should be fixed? */
- test_eq(-1, parse_rfc1123_time("Wed, 29 Feb 2011 16:00:00 GMT", &t_res));
- /* Why is this string valid (ie. the test fails because it doesn't
- return -1)? */
- test_eq(-1, parse_rfc1123_time("Wed, 30 Mar 2011 23:59:61 GMT", &t_res));
-#endif
+ tt_int_op(0,==, parse_rfc1123_time("Wed, 04 Aug 2004 00:48:22 ZUL", &t_res));
+ tt_int_op(t_res,==, (time_t)1091580502UL);
+ tt_int_op(-1,==,
+ parse_rfc1123_time("Wed, zz Aug 2004 99-99x99 GMT", &t_res));
+ tt_int_op(-1,==,
+ parse_rfc1123_time("Wed, 32 Mar 2011 00:00:00 GMT", &t_res));
+ tt_int_op(-1,==,
+ parse_rfc1123_time("Wed, 30 Mar 2011 24:00:00 GMT", &t_res));
+ tt_int_op(-1,==,
+ parse_rfc1123_time("Wed, 30 Mar 2011 23:60:00 GMT", &t_res));
+ tt_int_op(-1,==,
+ parse_rfc1123_time("Wed, 30 Mar 2011 23:59:62 GMT", &t_res));
+ tt_int_op(-1,==,
+ parse_rfc1123_time("Wed, 30 Mar 1969 23:59:59 GMT", &t_res));
+ tt_int_op(-1,==,
+ parse_rfc1123_time("Wed, 30 Ene 2011 23:59:59 GMT", &t_res));
+ tt_int_op(-1,==,
+ parse_rfc1123_time("Wed, 30 Mar 2011 23:59:59 GM", &t_res));
+
+ tt_int_op(-1,==,
+ parse_rfc1123_time("Wed, 29 Feb 2011 16:00:00 GMT", &t_res));
+ tt_int_op(-1,==,
+ parse_rfc1123_time("Wed, 30 Mar 2011 23:59:61 GMT", &t_res));
/* Test parse_iso_time */
t_res = 0;
i = parse_iso_time("", &t_res);
- test_eq(-1, i);
+ tt_int_op(-1,==, i);
t_res = 0;
i = parse_iso_time("2004-08-32 00:48:22", &t_res);
- test_eq(-1, i);
+ tt_int_op(-1,==, i);
t_res = 0;
i = parse_iso_time("1969-08-03 00:48:22", &t_res);
- test_eq(-1, i);
+ tt_int_op(-1,==, i);
t_res = 0;
i = parse_iso_time("2004-08-04 00:48:22", &t_res);
- test_eq(0,i);
- test_eq(t_res, (time_t)1091580502UL);
+ tt_int_op(0,==, i);
+ tt_int_op(t_res,==, (time_t)1091580502UL);
t_res = 0;
i = parse_iso_time("2004-8-4 0:48:22", &t_res);
- test_eq(0, i);
- test_eq(t_res, (time_t)1091580502UL);
- test_eq(-1, parse_iso_time("2004-08-zz 99-99x99 GMT", &t_res));
- test_eq(-1, parse_iso_time("2011-03-32 00:00:00 GMT", &t_res));
- test_eq(-1, parse_iso_time("2011-03-30 24:00:00 GMT", &t_res));
- test_eq(-1, parse_iso_time("2011-03-30 23:60:00 GMT", &t_res));
- test_eq(-1, parse_iso_time("2011-03-30 23:59:62 GMT", &t_res));
- test_eq(-1, parse_iso_time("1969-03-30 23:59:59 GMT", &t_res));
- test_eq(-1, parse_iso_time("2011-00-30 23:59:59 GMT", &t_res));
- test_eq(-1, parse_iso_time("2147483647-08-29 14:00:00", &t_res));
- test_eq(-1, parse_iso_time("2011-03-30 23:59", &t_res));
+ tt_int_op(0,==, i);
+ tt_int_op(t_res,==, (time_t)1091580502UL);
+ tt_int_op(-1,==, parse_iso_time("2004-08-zz 99-99x99 GMT", &t_res));
+ tt_int_op(-1,==, parse_iso_time("2011-03-32 00:00:00 GMT", &t_res));
+ tt_int_op(-1,==, parse_iso_time("2011-03-30 24:00:00 GMT", &t_res));
+ tt_int_op(-1,==, parse_iso_time("2011-03-30 23:60:00 GMT", &t_res));
+ tt_int_op(-1,==, parse_iso_time("2011-03-30 23:59:62 GMT", &t_res));
+ tt_int_op(-1,==, parse_iso_time("1969-03-30 23:59:59 GMT", &t_res));
+ tt_int_op(-1,==, parse_iso_time("2011-00-30 23:59:59 GMT", &t_res));
+ tt_int_op(-1,==, parse_iso_time("2147483647-08-29 14:00:00", &t_res));
+ tt_int_op(-1,==, parse_iso_time("2011-03-30 23:59", &t_res));
/* Test tor_gettimeofday */
@@ -370,7 +610,7 @@ test_util_time(void)
tv.tv_sec = (time_t)1326296338;
tv.tv_usec = 3060;
format_iso_time(timestr, (time_t)tv.tv_sec);
- test_streq("2012-01-11 15:38:58", timestr);
+ tt_str_op("2012-01-11 15:38:58",==, timestr);
/* The output of format_local_iso_time will vary by timezone, and setting
our timezone for testing purposes would be a nontrivial flaky pain.
Skip this test for now.
@@ -378,11 +618,11 @@ test_util_time(void)
test_streq("2012-01-11 10:38:58", timestr);
*/
format_iso_time_nospace(timestr, (time_t)tv.tv_sec);
- test_streq("2012-01-11T15:38:58", timestr);
- test_eq(strlen(timestr), ISO_TIME_LEN);
+ tt_str_op("2012-01-11T15:38:58",==, timestr);
+ tt_int_op(strlen(timestr),==, ISO_TIME_LEN);
format_iso_time_nospace_usec(timestr, &tv);
- test_streq("2012-01-11T15:38:58.003060", timestr);
- test_eq(strlen(timestr), ISO_TIME_USEC_LEN);
+ tt_str_op("2012-01-11T15:38:58.003060",==, timestr);
+ tt_int_op(strlen(timestr),==, ISO_TIME_USEC_LEN);
done:
;
@@ -403,55 +643,66 @@ test_util_parse_http_time(void *arg)
/* Test parse_http_time */
- test_eq(-1, parse_http_time("", &a_time));
- test_eq(-1, parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time));
- test_eq(-1, parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time));
- test_eq(-1, parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time));
- test_eq(-1, parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time));
- test_eq(-1, parse_http_time("Sunday, August the third", &a_time));
- test_eq(-1, parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time));
-
- test_eq(0, parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time));
- test_eq((time_t)775961302UL, tor_timegm(&a_time));
+ tt_int_op(-1,==,
+ parse_http_time("", &a_time));
+ tt_int_op(-1,==,
+ parse_http_time("Sunday, 32 Aug 2004 00:48:22 GMT", &a_time));
+ tt_int_op(-1,==,
+ parse_http_time("Sunday, 3 Aug 1869 00:48:22 GMT", &a_time));
+ tt_int_op(-1,==,
+ parse_http_time("Sunday, 32-Aug-94 00:48:22 GMT", &a_time));
+ tt_int_op(-1,==,
+ parse_http_time("Sunday, 3-Ago-04 00:48:22", &a_time));
+ tt_int_op(-1,==,
+ parse_http_time("Sunday, August the third", &a_time));
+ tt_int_op(-1,==,
+ parse_http_time("Wednesday,,04 Aug 1994 00:48:22 GMT", &a_time));
+
+ tt_int_op(0,==,
+ parse_http_time("Wednesday, 04 Aug 1994 00:48:22 GMT", &a_time));
+ tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time));
T("1994-08-04 00:48:22");
- test_eq(0, parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time));
- test_eq((time_t)775961302UL, tor_timegm(&a_time));
+ tt_int_op(0,==,
+ parse_http_time("Wednesday, 4 Aug 1994 0:48:22 GMT", &a_time));
+ tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time));
T("1994-08-04 00:48:22");
- test_eq(0, parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time));
- test_eq((time_t)775961302UL, tor_timegm(&a_time));
+ tt_int_op(0,==,
+ parse_http_time("Miercoles, 4 Aug 1994 0:48:22 GMT", &a_time));
+ tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time));
T("1994-08-04 00:48:22");
- test_eq(0, parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time));
- test_eq((time_t)775961302UL, tor_timegm(&a_time));
+ tt_int_op(0,==,
+ parse_http_time("Wednesday, 04-Aug-94 00:48:22 GMT", &a_time));
+ tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time));
T("1994-08-04 00:48:22");
- test_eq(0, parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time));
- test_eq((time_t)775961302UL, tor_timegm(&a_time));
+ tt_int_op(0,==, parse_http_time("Wednesday, 4-Aug-94 0:48:22 GMT", &a_time));
+ tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time));
T("1994-08-04 00:48:22");
- test_eq(0, parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time));
- test_eq((time_t)775961302UL, tor_timegm(&a_time));
+ tt_int_op(0,==, parse_http_time("Miercoles, 4-Aug-94 0:48:22 GMT", &a_time));
+ tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time));
T("1994-08-04 00:48:22");
- test_eq(0, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time));
- test_eq((time_t)775961302UL, tor_timegm(&a_time));
+ tt_int_op(0,==, parse_http_time("Wed Aug 04 00:48:22 1994", &a_time));
+ tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time));
T("1994-08-04 00:48:22");
- test_eq(0, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time));
- test_eq((time_t)775961302UL, tor_timegm(&a_time));
+ tt_int_op(0,==, parse_http_time("Wed Aug 4 0:48:22 1994", &a_time));
+ tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time));
T("1994-08-04 00:48:22");
- test_eq(0, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time));
- test_eq((time_t)775961302UL, tor_timegm(&a_time));
+ tt_int_op(0,==, parse_http_time("Mie Aug 4 0:48:22 1994", &a_time));
+ tt_int_op((time_t)775961302UL,==, tor_timegm(&a_time));
T("1994-08-04 00:48:22");
- test_eq(0, parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time));
- test_eq((time_t)1325376000UL, tor_timegm(&a_time));
+ tt_int_op(0,==, parse_http_time("Sun, 1 Jan 2012 00:00:00 GMT", &a_time));
+ tt_int_op((time_t)1325376000UL,==, tor_timegm(&a_time));
T("2012-01-01 00:00:00");
- test_eq(0, parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time));
- test_eq((time_t)1356912000UL, tor_timegm(&a_time));
+ tt_int_op(0,==, parse_http_time("Mon, 31 Dec 2012 00:00:00 GMT", &a_time));
+ tt_int_op((time_t)1356912000UL,==, tor_timegm(&a_time));
T("2012-12-31 00:00:00");
- test_eq(-1, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time));
- test_eq(-1, parse_http_time("2011-03-32 00:00:00 GMT", &a_time));
- test_eq(-1, parse_http_time("2011-03-30 24:00:00 GMT", &a_time));
- test_eq(-1, parse_http_time("2011-03-30 23:60:00 GMT", &a_time));
- test_eq(-1, parse_http_time("2011-03-30 23:59:62 GMT", &a_time));
- test_eq(-1, parse_http_time("1969-03-30 23:59:59 GMT", &a_time));
- test_eq(-1, parse_http_time("2011-00-30 23:59:59 GMT", &a_time));
- test_eq(-1, parse_http_time("2011-03-30 23:59", &a_time));
+ tt_int_op(-1,==, parse_http_time("2004-08-zz 99-99x99 GMT", &a_time));
+ tt_int_op(-1,==, parse_http_time("2011-03-32 00:00:00 GMT", &a_time));
+ tt_int_op(-1,==, parse_http_time("2011-03-30 24:00:00 GMT", &a_time));
+ tt_int_op(-1,==, parse_http_time("2011-03-30 23:60:00 GMT", &a_time));
+ tt_int_op(-1,==, parse_http_time("2011-03-30 23:59:62 GMT", &a_time));
+ tt_int_op(-1,==, parse_http_time("1969-03-30 23:59:59 GMT", &a_time));
+ tt_int_op(-1,==, parse_http_time("2011-00-30 23:59:59 GMT", &a_time));
+ tt_int_op(-1,==, parse_http_time("2011-03-30 23:59", &a_time));
#undef T
done:
@@ -459,13 +710,14 @@ test_util_parse_http_time(void *arg)
}
static void
-test_util_config_line(void)
+test_util_config_line(void *arg)
{
char buf[1024];
char *k=NULL, *v=NULL;
const char *str;
/* Test parse_config_line_from_str */
+ (void)arg;
strlcpy(buf, "k v\n" " key value with spaces \n" "keykey val\n"
"k2\n"
"k3 \n" "\n" " \n" "#comment\n"
@@ -485,110 +737,110 @@ test_util_config_line(void)
str = buf;
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k");
- test_streq(v, "v");
+ tt_str_op(k,==, "k");
+ tt_str_op(v,==, "v");
tor_free(k); tor_free(v);
- test_assert(!strcmpstart(str, "key value with"));
+ tt_assert(!strcmpstart(str, "key value with"));
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "key");
- test_streq(v, "value with spaces");
+ tt_str_op(k,==, "key");
+ tt_str_op(v,==, "value with spaces");
tor_free(k); tor_free(v);
- test_assert(!strcmpstart(str, "keykey"));
+ tt_assert(!strcmpstart(str, "keykey"));
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "keykey");
- test_streq(v, "val");
+ tt_str_op(k,==, "keykey");
+ tt_str_op(v,==, "val");
tor_free(k); tor_free(v);
- test_assert(!strcmpstart(str, "k2\n"));
+ tt_assert(!strcmpstart(str, "k2\n"));
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k2");
- test_streq(v, "");
+ tt_str_op(k,==, "k2");
+ tt_str_op(v,==, "");
tor_free(k); tor_free(v);
- test_assert(!strcmpstart(str, "k3 \n"));
+ tt_assert(!strcmpstart(str, "k3 \n"));
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k3");
- test_streq(v, "");
+ tt_str_op(k,==, "k3");
+ tt_str_op(v,==, "");
tor_free(k); tor_free(v);
- test_assert(!strcmpstart(str, "#comment"));
+ tt_assert(!strcmpstart(str, "#comment"));
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k4");
- test_streq(v, "");
+ tt_str_op(k,==, "k4");
+ tt_str_op(v,==, "");
tor_free(k); tor_free(v);
- test_assert(!strcmpstart(str, "k5#abc"));
+ tt_assert(!strcmpstart(str, "k5#abc"));
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k5");
- test_streq(v, "");
+ tt_str_op(k,==, "k5");
+ tt_str_op(v,==, "");
tor_free(k); tor_free(v);
- test_assert(!strcmpstart(str, "k6"));
+ tt_assert(!strcmpstart(str, "k6"));
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k6");
- test_streq(v, "val");
+ tt_str_op(k,==, "k6");
+ tt_str_op(v,==, "val");
tor_free(k); tor_free(v);
- test_assert(!strcmpstart(str, "kseven"));
+ tt_assert(!strcmpstart(str, "kseven"));
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "kseven");
- test_streq(v, "a quoted \'string");
+ tt_str_op(k,==, "kseven");
+ tt_str_op(v,==, "a quoted \'string");
tor_free(k); tor_free(v);
- test_assert(!strcmpstart(str, "k8 "));
+ tt_assert(!strcmpstart(str, "k8 "));
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k8");
- test_streq(v, "a quoted\n\"str\\ing\t\x01\x01\x01\"");
+ tt_str_op(k,==, "k8");
+ tt_str_op(v,==, "a quoted\n\"str\\ing\t\x01\x01\x01\"");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k9");
- test_streq(v, "a line that spans two lines.");
+ tt_str_op(k,==, "k9");
+ tt_str_op(v,==, "a line that spans two lines.");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k10");
- test_streq(v, "more than one continuation");
+ tt_str_op(k,==, "k10");
+ tt_str_op(v,==, "more than one continuation");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k11");
- test_streq(v, "continuation at the start");
+ tt_str_op(k,==, "k11");
+ tt_str_op(v,==, "continuation at the start");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k12");
- test_streq(v, "line with a embedded");
+ tt_str_op(k,==, "k12");
+ tt_str_op(v,==, "line with a embedded");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k13");
- test_streq(v, "continuation at the very start");
+ tt_str_op(k,==, "k13");
+ tt_str_op(v,==, "continuation at the very start");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k14");
- test_streq(v, "a line that has a comment and" );
+ tt_str_op(k,==, "k14");
+ tt_str_op(v,==, "a line that has a comment and" );
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k15");
- test_streq(v, "this should be the next new line");
+ tt_str_op(k,==, "k15");
+ tt_str_op(v,==, "this should be the next new line");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k16");
- test_streq(v, "a line that has a comment and" );
+ tt_str_op(k,==, "k16");
+ tt_str_op(v,==, "a line that has a comment and" );
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k17");
- test_streq(v, "this should be the next new line");
+ tt_str_op(k,==, "k17");
+ tt_str_op(v,==, "this should be the next new line");
tor_free(k); tor_free(v);
- test_streq(str, "");
+ tt_str_op(str,==, "");
done:
tor_free(k);
@@ -596,7 +848,7 @@ test_util_config_line(void)
}
static void
-test_util_config_line_quotes(void)
+test_util_config_line_quotes(void *arg)
{
char buf1[1024];
char buf2[128];
@@ -606,6 +858,7 @@ test_util_config_line_quotes(void)
const char *str;
/* Test parse_config_line_from_str */
+ (void)arg;
strlcpy(buf1, "kTrailingSpace \"quoted value\" \n"
"kTrailingGarbage \"quoted value\"trailing garbage\n"
, sizeof(buf1));
@@ -618,30 +871,30 @@ test_util_config_line_quotes(void)
str = buf1;
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "kTrailingSpace");
- test_streq(v, "quoted value");
+ tt_str_op(k,==, "kTrailingSpace");
+ tt_str_op(v,==, "quoted value");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_eq_ptr(str, NULL);
+ tt_ptr_op(str,==, NULL);
tor_free(k); tor_free(v);
str = buf2;
str = parse_config_line_from_str(str, &k, &v);
- test_eq_ptr(str, NULL);
+ tt_ptr_op(str,==, NULL);
tor_free(k); tor_free(v);
str = buf3;
str = parse_config_line_from_str(str, &k, &v);
- test_eq_ptr(str, NULL);
+ tt_ptr_op(str,==, NULL);
tor_free(k); tor_free(v);
str = buf4;
str = parse_config_line_from_str(str, &k, &v);
- test_eq_ptr(str, NULL);
+ tt_ptr_op(str,==, NULL);
tor_free(k); tor_free(v);
done:
@@ -650,13 +903,14 @@ test_util_config_line_quotes(void)
}
static void
-test_util_config_line_comment_character(void)
+test_util_config_line_comment_character(void *arg)
{
char buf[1024];
char *k=NULL, *v=NULL;
const char *str;
/* Test parse_config_line_from_str */
+ (void)arg;
strlcpy(buf, "k1 \"# in quotes\"\n"
"k2 some value # some comment\n"
"k3 /home/user/myTorNetwork#2\n" /* Testcase for #1323 */
@@ -664,16 +918,16 @@ test_util_config_line_comment_character(void)
str = buf;
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k1");
- test_streq(v, "# in quotes");
+ tt_str_op(k,==, "k1");
+ tt_str_op(v,==, "# in quotes");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "k2");
- test_streq(v, "some value");
+ tt_str_op(k,==, "k2");
+ tt_str_op(v,==, "some value");
tor_free(k); tor_free(v);
- test_streq(str, "k3 /home/user/myTorNetwork#2\n");
+ tt_str_op(str,==, "k3 /home/user/myTorNetwork#2\n");
#if 0
str = parse_config_line_from_str(str, &k, &v);
@@ -690,7 +944,7 @@ test_util_config_line_comment_character(void)
}
static void
-test_util_config_line_escaped_content(void)
+test_util_config_line_escaped_content(void *arg)
{
char buf1[1024];
char buf2[128];
@@ -702,6 +956,7 @@ test_util_config_line_escaped_content(void)
const char *str;
/* Test parse_config_line_from_str */
+ (void)arg;
strlcpy(buf1, "HexadecimalLower \"\\x2a\"\n"
"HexadecimalUpper \"\\x2A\"\n"
"HexadecimalUpperX \"\\X2A\"\n"
@@ -733,91 +988,91 @@ test_util_config_line_escaped_content(void)
str = buf1;
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "HexadecimalLower");
- test_streq(v, "*");
+ tt_str_op(k,==, "HexadecimalLower");
+ tt_str_op(v,==, "*");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "HexadecimalUpper");
- test_streq(v, "*");
+ tt_str_op(k,==, "HexadecimalUpper");
+ tt_str_op(v,==, "*");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "HexadecimalUpperX");
- test_streq(v, "*");
+ tt_str_op(k,==, "HexadecimalUpperX");
+ tt_str_op(v,==, "*");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "Octal");
- test_streq(v, "*");
+ tt_str_op(k,==, "Octal");
+ tt_str_op(v,==, "*");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "Newline");
- test_streq(v, "\n");
+ tt_str_op(k,==, "Newline");
+ tt_str_op(v,==, "\n");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "Tab");
- test_streq(v, "\t");
+ tt_str_op(k,==, "Tab");
+ tt_str_op(v,==, "\t");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "CarriageReturn");
- test_streq(v, "\r");
+ tt_str_op(k,==, "CarriageReturn");
+ tt_str_op(v,==, "\r");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "DoubleQuote");
- test_streq(v, "\"");
+ tt_str_op(k,==, "DoubleQuote");
+ tt_str_op(v,==, "\"");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "SimpleQuote");
- test_streq(v, "'");
+ tt_str_op(k,==, "SimpleQuote");
+ tt_str_op(v,==, "'");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "Backslash");
- test_streq(v, "\\");
+ tt_str_op(k,==, "Backslash");
+ tt_str_op(v,==, "\\");
tor_free(k); tor_free(v);
str = parse_config_line_from_str(str, &k, &v);
- test_streq(k, "Mix");
- test_streq(v, "This is a \"star\":\t'*'\nAnd second line");
+ tt_str_op(k,==, "Mix");
+ tt_str_op(v,==, "This is a \"star\":\t'*'\nAnd second line");
tor_free(k); tor_free(v);
- test_streq(str, "");
+ tt_str_op(str,==, "");
str = buf2;
str = parse_config_line_from_str(str, &k, &v);
- test_eq_ptr(str, NULL);
+ tt_ptr_op(str,==, NULL);
tor_free(k); tor_free(v);
str = buf3;
str = parse_config_line_from_str(str, &k, &v);
- test_eq_ptr(str, NULL);
+ tt_ptr_op(str,==, NULL);
tor_free(k); tor_free(v);
str = buf4;
str = parse_config_line_from_str(str, &k, &v);
- test_eq_ptr(str, NULL);
+ tt_ptr_op(str,==, NULL);
tor_free(k); tor_free(v);
#if 0
str = buf5;
str = parse_config_line_from_str(str, &k, &v);
- test_eq_ptr(str, NULL);
+ tt_ptr_op(str, ==, NULL);
tor_free(k); tor_free(v);
#endif
str = buf6;
str = parse_config_line_from_str(str, &k, &v);
- test_eq_ptr(str, NULL);
+ tt_ptr_op(str,==, NULL);
tor_free(k); tor_free(v);
done:
@@ -827,46 +1082,47 @@ test_util_config_line_escaped_content(void)
#ifndef _WIN32
static void
-test_util_expand_filename(void)
+test_util_expand_filename(void *arg)
{
char *str;
+ (void)arg;
setenv("HOME", "/home/itv", 1); /* For "internal test value" */
str = expand_filename("");
- test_streq("", str);
+ tt_str_op("",==, str);
tor_free(str);
str = expand_filename("/normal/path");
- test_streq("/normal/path", str);
+ tt_str_op("/normal/path",==, str);
tor_free(str);
str = expand_filename("/normal/trailing/path/");
- test_streq("/normal/trailing/path/", str);
+ tt_str_op("/normal/trailing/path/",==, str);
tor_free(str);
str = expand_filename("~");
- test_streq("/home/itv/", str);
+ tt_str_op("/home/itv/",==, str);
tor_free(str);
str = expand_filename("$HOME/nodice");
- test_streq("$HOME/nodice", str);
+ tt_str_op("$HOME/nodice",==, str);
tor_free(str);
str = expand_filename("~/");
- test_streq("/home/itv/", str);
+ tt_str_op("/home/itv/",==, str);
tor_free(str);
str = expand_filename("~/foobarqux");
- test_streq("/home/itv/foobarqux", str);
+ tt_str_op("/home/itv/foobarqux",==, str);
tor_free(str);
str = expand_filename("~/../../etc/passwd");
- test_streq("/home/itv/../../etc/passwd", str);
+ tt_str_op("/home/itv/../../etc/passwd",==, str);
tor_free(str);
str = expand_filename("~/trailing/");
- test_streq("/home/itv/trailing/", str);
+ tt_str_op("/home/itv/trailing/",==, str);
tor_free(str);
/* Ideally we'd test ~anotheruser, but that's shady to test (we'd
have to somehow inject/fake the get_user_homedir call) */
@@ -875,15 +1131,15 @@ test_util_expand_filename(void)
setenv("HOME", "/home/itv/", 1);
str = expand_filename("~");
- test_streq("/home/itv/", str);
+ tt_str_op("/home/itv/",==, str);
tor_free(str);
str = expand_filename("~/");
- test_streq("/home/itv/", str);
+ tt_str_op("/home/itv/",==, str);
tor_free(str);
str = expand_filename("~/foo");
- test_streq("/home/itv/foo", str);
+ tt_str_op("/home/itv/foo",==, str);
tor_free(str);
/* Try with empty $HOME */
@@ -891,15 +1147,15 @@ test_util_expand_filename(void)
setenv("HOME", "", 1);
str = expand_filename("~");
- test_streq("/", str);
+ tt_str_op("/",==, str);
tor_free(str);
str = expand_filename("~/");
- test_streq("/", str);
+ tt_str_op("/",==, str);
tor_free(str);
str = expand_filename("~/foobar");
- test_streq("/foobar", str);
+ tt_str_op("/foobar",==, str);
tor_free(str);
/* Try with $HOME unset */
@@ -907,15 +1163,15 @@ test_util_expand_filename(void)
unsetenv("HOME");
str = expand_filename("~");
- test_streq("/", str);
+ tt_str_op("/",==, str);
tor_free(str);
str = expand_filename("~/");
- test_streq("/", str);
+ tt_str_op("/",==, str);
tor_free(str);
str = expand_filename("~/foobar");
- test_streq("/foobar", str);
+ tt_str_op("/foobar",==, str);
tor_free(str);
done:
@@ -925,37 +1181,38 @@ test_util_expand_filename(void)
/** Test tor_escape_str_for_pt_args(). */
static void
-test_util_escape_string_socks(void)
+test_util_escape_string_socks(void *arg)
{
char *escaped_string = NULL;
/** Simple backslash escape. */
+ (void)arg;
escaped_string = tor_escape_str_for_pt_args("This is a backslash: \\",";\\");
- test_assert(escaped_string);
- test_streq(escaped_string, "This is a backslash: \\\\");
+ tt_assert(escaped_string);
+ tt_str_op(escaped_string,==, "This is a backslash: \\\\");
tor_free(escaped_string);
/** Simple semicolon escape. */
escaped_string = tor_escape_str_for_pt_args("First rule:Do not use ;",";\\");
- test_assert(escaped_string);
- test_streq(escaped_string, "First rule:Do not use \\;");
+ tt_assert(escaped_string);
+ tt_str_op(escaped_string,==, "First rule:Do not use \\;");
tor_free(escaped_string);
/** Empty string. */
escaped_string = tor_escape_str_for_pt_args("", ";\\");
- test_assert(escaped_string);
- test_streq(escaped_string, "");
+ tt_assert(escaped_string);
+ tt_str_op(escaped_string,==, "");
tor_free(escaped_string);
/** Escape all characters. */
escaped_string = tor_escape_str_for_pt_args(";\\;\\", ";\\");
- test_assert(escaped_string);
- test_streq(escaped_string, "\\;\\\\\\;\\\\");
+ tt_assert(escaped_string);
+ tt_str_op(escaped_string,==, "\\;\\\\\\;\\\\");
tor_free(escaped_string);
escaped_string = tor_escape_str_for_pt_args(";", ";\\");
- test_assert(escaped_string);
- test_streq(escaped_string, "\\;");
+ tt_assert(escaped_string);
+ tt_str_op(escaped_string,==, "\\;");
tor_free(escaped_string);
done:
@@ -966,288 +1223,290 @@ static void
test_util_string_is_key_value(void *ptr)
{
(void)ptr;
- test_assert(string_is_key_value(LOG_WARN, "key=value"));
- test_assert(string_is_key_value(LOG_WARN, "k=v"));
- test_assert(string_is_key_value(LOG_WARN, "key="));
- test_assert(string_is_key_value(LOG_WARN, "x="));
- test_assert(string_is_key_value(LOG_WARN, "xx="));
- test_assert(!string_is_key_value(LOG_WARN, "=value"));
- test_assert(!string_is_key_value(LOG_WARN, "=x"));
- test_assert(!string_is_key_value(LOG_WARN, "="));
+ tt_assert(string_is_key_value(LOG_WARN, "key=value"));
+ tt_assert(string_is_key_value(LOG_WARN, "k=v"));
+ tt_assert(string_is_key_value(LOG_WARN, "key="));
+ tt_assert(string_is_key_value(LOG_WARN, "x="));
+ tt_assert(string_is_key_value(LOG_WARN, "xx="));
+ tt_assert(!string_is_key_value(LOG_WARN, "=value"));
+ tt_assert(!string_is_key_value(LOG_WARN, "=x"));
+ tt_assert(!string_is_key_value(LOG_WARN, "="));
/* ??? */
- /* test_assert(!string_is_key_value(LOG_WARN, "===")); */
+ /* tt_assert(!string_is_key_value(LOG_WARN, "===")); */
done:
;
}
/** Test basic string functionality. */
static void
-test_util_strmisc(void)
+test_util_strmisc(void *arg)
{
char buf[1024];
int i;
char *cp, *cp_tmp = NULL;
/* Test strl operations */
- test_eq(5, strlcpy(buf, "Hello", 0));
- test_eq(5, strlcpy(buf, "Hello", 10));
- test_streq(buf, "Hello");
- test_eq(5, strlcpy(buf, "Hello", 6));
- test_streq(buf, "Hello");
- test_eq(5, strlcpy(buf, "Hello", 5));
- test_streq(buf, "Hell");
+ (void)arg;
+ tt_int_op(5,==, strlcpy(buf, "Hello", 0));
+ tt_int_op(5,==, strlcpy(buf, "Hello", 10));
+ tt_str_op(buf,==, "Hello");
+ tt_int_op(5,==, strlcpy(buf, "Hello", 6));
+ tt_str_op(buf,==, "Hello");
+ tt_int_op(5,==, strlcpy(buf, "Hello", 5));
+ tt_str_op(buf,==, "Hell");
strlcpy(buf, "Hello", sizeof(buf));
- test_eq(10, strlcat(buf, "Hello", 5));
+ tt_int_op(10,==, strlcat(buf, "Hello", 5));
/* Test strstrip() */
strlcpy(buf, "Testing 1 2 3", sizeof(buf));
tor_strstrip(buf, ",!");
- test_streq(buf, "Testing 1 2 3");
+ tt_str_op(buf,==, "Testing 1 2 3");
strlcpy(buf, "!Testing 1 2 3?", sizeof(buf));
tor_strstrip(buf, "!? ");
- test_streq(buf, "Testing123");
+ tt_str_op(buf,==, "Testing123");
strlcpy(buf, "!!!Testing 1 2 3??", sizeof(buf));
tor_strstrip(buf, "!? ");
- test_streq(buf, "Testing123");
+ tt_str_op(buf,==, "Testing123");
/* Test parse_long */
/* Empty/zero input */
- test_eq(0L, tor_parse_long("",10,0,100,&i,NULL));
- test_eq(0, i);
- test_eq(0L, tor_parse_long("0",10,0,100,&i,NULL));
- test_eq(1, i);
+ tt_int_op(0L,==, tor_parse_long("",10,0,100,&i,NULL));
+ tt_int_op(0,==, i);
+ tt_int_op(0L,==, tor_parse_long("0",10,0,100,&i,NULL));
+ tt_int_op(1,==, i);
/* Normal cases */
- test_eq(10L, tor_parse_long("10",10,0,100,&i,NULL));
- test_eq(1, i);
- test_eq(10L, tor_parse_long("10",10,0,10,&i,NULL));
- test_eq(1, i);
- test_eq(10L, tor_parse_long("10",10,10,100,&i,NULL));
- test_eq(1, i);
- test_eq(-50L, tor_parse_long("-50",10,-100,100,&i,NULL));
- test_eq(1, i);
- test_eq(-50L, tor_parse_long("-50",10,-100,0,&i,NULL));
- test_eq(1, i);
- test_eq(-50L, tor_parse_long("-50",10,-50,0,&i,NULL));
- test_eq(1, i);
+ tt_int_op(10L,==, tor_parse_long("10",10,0,100,&i,NULL));
+ tt_int_op(1,==, i);
+ tt_int_op(10L,==, tor_parse_long("10",10,0,10,&i,NULL));
+ tt_int_op(1,==, i);
+ tt_int_op(10L,==, tor_parse_long("10",10,10,100,&i,NULL));
+ tt_int_op(1,==, i);
+ tt_int_op(-50L,==, tor_parse_long("-50",10,-100,100,&i,NULL));
+ tt_int_op(1,==, i);
+ tt_int_op(-50L,==, tor_parse_long("-50",10,-100,0,&i,NULL));
+ tt_int_op(1,==, i);
+ tt_int_op(-50L,==, tor_parse_long("-50",10,-50,0,&i,NULL));
+ tt_int_op(1,==, i);
/* Extra garbage */
- test_eq(0L, tor_parse_long("10m",10,0,100,&i,NULL));
- test_eq(0, i);
- test_eq(0L, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL));
- test_eq(0, i);
- test_eq(10L, tor_parse_long("10m",10,0,100,&i,&cp));
- test_eq(1, i);
- test_streq(cp, "m");
- test_eq(-50L, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp));
- test_eq(1, i);
- test_streq(cp, " plus garbage");
+ tt_int_op(0L,==, tor_parse_long("10m",10,0,100,&i,NULL));
+ tt_int_op(0,==, i);
+ tt_int_op(0L,==, tor_parse_long("-50 plus garbage",10,-100,100,&i,NULL));
+ tt_int_op(0,==, i);
+ tt_int_op(10L,==, tor_parse_long("10m",10,0,100,&i,&cp));
+ tt_int_op(1,==, i);
+ tt_str_op(cp,==, "m");
+ tt_int_op(-50L,==, tor_parse_long("-50 plus garbage",10,-100,100,&i,&cp));
+ tt_int_op(1,==, i);
+ tt_str_op(cp,==, " plus garbage");
/* Out of bounds */
- test_eq(0L, tor_parse_long("10",10,50,100,&i,NULL));
- test_eq(0, i);
- test_eq(0L, tor_parse_long("-50",10,0,100,&i,NULL));
- test_eq(0, i);
+ tt_int_op(0L,==, tor_parse_long("10",10,50,100,&i,NULL));
+ tt_int_op(0,==, i);
+ tt_int_op(0L,==, tor_parse_long("-50",10,0,100,&i,NULL));
+ tt_int_op(0,==, i);
/* Base different than 10 */
- test_eq(2L, tor_parse_long("10",2,0,100,NULL,NULL));
- test_eq(0L, tor_parse_long("2",2,0,100,NULL,NULL));
- test_eq(0L, tor_parse_long("10",-2,0,100,NULL,NULL));
- test_eq(68284L, tor_parse_long("10abc",16,0,70000,NULL,NULL));
- test_eq(68284L, tor_parse_long("10ABC",16,0,70000,NULL,NULL));
- test_eq(0, tor_parse_long("10ABC",-1,0,70000,&i,NULL));
- test_eq(i, 0);
+ tt_int_op(2L,==, tor_parse_long("10",2,0,100,NULL,NULL));
+ tt_int_op(0L,==, tor_parse_long("2",2,0,100,NULL,NULL));
+ tt_int_op(0L,==, tor_parse_long("10",-2,0,100,NULL,NULL));
+ tt_int_op(68284L,==, tor_parse_long("10abc",16,0,70000,NULL,NULL));
+ tt_int_op(68284L,==, tor_parse_long("10ABC",16,0,70000,NULL,NULL));
+ tt_int_op(0,==, tor_parse_long("10ABC",-1,0,70000,&i,NULL));
+ tt_int_op(i,==, 0);
/* Test parse_ulong */
- test_eq(0UL, tor_parse_ulong("",10,0,100,NULL,NULL));
- test_eq(0UL, tor_parse_ulong("0",10,0,100,NULL,NULL));
- test_eq(10UL, tor_parse_ulong("10",10,0,100,NULL,NULL));
- test_eq(0UL, tor_parse_ulong("10",10,50,100,NULL,NULL));
- test_eq(10UL, tor_parse_ulong("10",10,0,10,NULL,NULL));
- test_eq(10UL, tor_parse_ulong("10",10,10,100,NULL,NULL));
- test_eq(0UL, tor_parse_ulong("8",8,0,100,NULL,NULL));
- test_eq(50UL, tor_parse_ulong("50",10,50,100,NULL,NULL));
- test_eq(0UL, tor_parse_ulong("-50",10,-100,100,NULL,NULL));
- test_eq(0UL, tor_parse_ulong("50",-1,50,100,&i,NULL));
- test_eq(0, i);
+ tt_int_op(0UL,==, tor_parse_ulong("",10,0,100,NULL,NULL));
+ tt_int_op(0UL,==, tor_parse_ulong("0",10,0,100,NULL,NULL));
+ tt_int_op(10UL,==, tor_parse_ulong("10",10,0,100,NULL,NULL));
+ tt_int_op(0UL,==, tor_parse_ulong("10",10,50,100,NULL,NULL));
+ tt_int_op(10UL,==, tor_parse_ulong("10",10,0,10,NULL,NULL));
+ tt_int_op(10UL,==, tor_parse_ulong("10",10,10,100,NULL,NULL));
+ tt_int_op(0UL,==, tor_parse_ulong("8",8,0,100,NULL,NULL));
+ tt_int_op(50UL,==, tor_parse_ulong("50",10,50,100,NULL,NULL));
+ tt_int_op(0UL,==, tor_parse_ulong("-50",10,-100,100,NULL,NULL));
+ tt_int_op(0UL,==, tor_parse_ulong("50",-1,50,100,&i,NULL));
+ tt_int_op(0,==, i);
/* Test parse_uint64 */
- test_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
- test_eq(1, i);
- test_streq(cp, " x");
- test_assert(U64_LITERAL(12345678901) ==
+ tt_assert(U64_LITERAL(10) == tor_parse_uint64("10 x",10,0,100, &i, &cp));
+ tt_int_op(1,==, i);
+ tt_str_op(cp,==, " x");
+ tt_assert(U64_LITERAL(12345678901) ==
tor_parse_uint64("12345678901",10,0,UINT64_MAX, &i, &cp));
- test_eq(1, i);
- test_streq(cp, "");
- test_assert(U64_LITERAL(0) ==
+ tt_int_op(1,==, i);
+ tt_str_op(cp,==, "");
+ tt_assert(U64_LITERAL(0) ==
tor_parse_uint64("12345678901",10,500,INT32_MAX, &i, &cp));
- test_eq(0, i);
- test_assert(U64_LITERAL(0) ==
+ tt_int_op(0,==, i);
+ tt_assert(U64_LITERAL(0) ==
tor_parse_uint64("123",-1,0,INT32_MAX, &i, &cp));
- test_eq(0, i);
+ tt_int_op(0,==, i);
{
/* Test parse_double */
double d = tor_parse_double("10", 0, UINT64_MAX,&i,NULL);
- test_eq(1, i);
- test_assert(DBL_TO_U64(d) == 10);
+ tt_int_op(1,==, i);
+ tt_assert(DBL_TO_U64(d) == 10);
d = tor_parse_double("0", 0, UINT64_MAX,&i,NULL);
- test_eq(1, i);
- test_assert(DBL_TO_U64(d) == 0);
+ tt_int_op(1,==, i);
+ tt_assert(DBL_TO_U64(d) == 0);
d = tor_parse_double(" ", 0, UINT64_MAX,&i,NULL);
- test_eq(0, i);
+ tt_int_op(0,==, i);
d = tor_parse_double(".0a", 0, UINT64_MAX,&i,NULL);
- test_eq(0, i);
+ tt_int_op(0,==, i);
d = tor_parse_double(".0a", 0, UINT64_MAX,&i,&cp);
- test_eq(1, i);
+ tt_int_op(1,==, i);
d = tor_parse_double("-.0", 0, UINT64_MAX,&i,NULL);
- test_eq(1, i);
- test_assert(DBL_TO_U64(d) == 0);
+ tt_int_op(1,==, i);
+ tt_assert(DBL_TO_U64(d) == 0);
d = tor_parse_double("-10", -100.0, 100.0,&i,NULL);
- test_eq(1, i);
- test_eq(-10.0, d);
+ tt_int_op(1,==, i);
+ tt_int_op(-10.0,==, d);
}
{
/* Test tor_parse_* where we overflow/underflow the underlying type. */
/* This string should overflow 64-bit ints. */
#define TOOBIG "100000000000000000000000000"
- test_eq(0L, tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
- test_eq(i, 0);
- test_eq(0L, tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
- test_eq(i, 0);
- test_eq(0UL, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL));
- test_eq(i, 0);
+ tt_int_op(0L,==, tor_parse_long(TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
+ tt_int_op(i,==, 0);
+ tt_int_op(0L,==,
+ tor_parse_long("-"TOOBIG, 10, LONG_MIN, LONG_MAX, &i, NULL));
+ tt_int_op(i,==, 0);
+ tt_int_op(0UL,==, tor_parse_ulong(TOOBIG, 10, 0, ULONG_MAX, &i, NULL));
+ tt_int_op(i,==, 0);
tt_u64_op(U64_LITERAL(0), ==, tor_parse_uint64(TOOBIG, 10,
0, UINT64_MAX, &i, NULL));
- test_eq(i, 0);
+ tt_int_op(i,==, 0);
}
/* Test snprintf */
/* Returning -1 when there's not enough room in the output buffer */
- test_eq(-1, tor_snprintf(buf, 0, "Foo"));
- test_eq(-1, tor_snprintf(buf, 2, "Foo"));
- test_eq(-1, tor_snprintf(buf, 3, "Foo"));
- test_neq(-1, tor_snprintf(buf, 4, "Foo"));
+ tt_int_op(-1,==, tor_snprintf(buf, 0, "Foo"));
+ tt_int_op(-1,==, tor_snprintf(buf, 2, "Foo"));
+ tt_int_op(-1,==, tor_snprintf(buf, 3, "Foo"));
+ tt_int_op(-1,!=, tor_snprintf(buf, 4, "Foo"));
/* Always NUL-terminate the output */
tor_snprintf(buf, 5, "abcdef");
- test_eq(0, buf[4]);
+ tt_int_op(0,==, buf[4]);
tor_snprintf(buf, 10, "abcdef");
- test_eq(0, buf[6]);
+ tt_int_op(0,==, buf[6]);
/* uint64 */
tor_snprintf(buf, sizeof(buf), "x!"U64_FORMAT"!x",
U64_PRINTF_ARG(U64_LITERAL(12345678901)));
- test_streq("x!12345678901!x", buf);
+ tt_str_op("x!12345678901!x",==, buf);
/* Test str{,case}cmpstart */
- test_assert(strcmpstart("abcdef", "abcdef")==0);
- test_assert(strcmpstart("abcdef", "abc")==0);
- test_assert(strcmpstart("abcdef", "abd")<0);
- test_assert(strcmpstart("abcdef", "abb")>0);
- test_assert(strcmpstart("ab", "abb")<0);
- test_assert(strcmpstart("ab", "")==0);
- test_assert(strcmpstart("ab", "ab ")<0);
- test_assert(strcasecmpstart("abcdef", "abCdEF")==0);
- test_assert(strcasecmpstart("abcDeF", "abc")==0);
- test_assert(strcasecmpstart("abcdef", "Abd")<0);
- test_assert(strcasecmpstart("Abcdef", "abb")>0);
- test_assert(strcasecmpstart("ab", "Abb")<0);
- test_assert(strcasecmpstart("ab", "")==0);
- test_assert(strcasecmpstart("ab", "ab ")<0);
+ tt_assert(strcmpstart("abcdef", "abcdef")==0);
+ tt_assert(strcmpstart("abcdef", "abc")==0);
+ tt_assert(strcmpstart("abcdef", "abd")<0);
+ tt_assert(strcmpstart("abcdef", "abb")>0);
+ tt_assert(strcmpstart("ab", "abb")<0);
+ tt_assert(strcmpstart("ab", "")==0);
+ tt_assert(strcmpstart("ab", "ab ")<0);
+ tt_assert(strcasecmpstart("abcdef", "abCdEF")==0);
+ tt_assert(strcasecmpstart("abcDeF", "abc")==0);
+ tt_assert(strcasecmpstart("abcdef", "Abd")<0);
+ tt_assert(strcasecmpstart("Abcdef", "abb")>0);
+ tt_assert(strcasecmpstart("ab", "Abb")<0);
+ tt_assert(strcasecmpstart("ab", "")==0);
+ tt_assert(strcasecmpstart("ab", "ab ")<0);
/* Test str{,case}cmpend */
- test_assert(strcmpend("abcdef", "abcdef")==0);
- test_assert(strcmpend("abcdef", "def")==0);
- test_assert(strcmpend("abcdef", "deg")<0);
- test_assert(strcmpend("abcdef", "dee")>0);
- test_assert(strcmpend("ab", "aab")>0);
- test_assert(strcasecmpend("AbcDEF", "abcdef")==0);
- test_assert(strcasecmpend("abcdef", "dEF")==0);
- test_assert(strcasecmpend("abcdef", "Deg")<0);
- test_assert(strcasecmpend("abcDef", "dee")>0);
- test_assert(strcasecmpend("AB", "abb")<0);
+ tt_assert(strcmpend("abcdef", "abcdef")==0);
+ tt_assert(strcmpend("abcdef", "def")==0);
+ tt_assert(strcmpend("abcdef", "deg")<0);
+ tt_assert(strcmpend("abcdef", "dee")>0);
+ tt_assert(strcmpend("ab", "aab")>0);
+ tt_assert(strcasecmpend("AbcDEF", "abcdef")==0);
+ tt_assert(strcasecmpend("abcdef", "dEF")==0);
+ tt_assert(strcasecmpend("abcdef", "Deg")<0);
+ tt_assert(strcasecmpend("abcDef", "dee")>0);
+ tt_assert(strcasecmpend("AB", "abb")<0);
/* Test digest_is_zero */
memset(buf,0,20);
buf[20] = 'x';
- test_assert(tor_digest_is_zero(buf));
+ tt_assert(tor_digest_is_zero(buf));
buf[19] = 'x';
- test_assert(!tor_digest_is_zero(buf));
+ tt_assert(!tor_digest_is_zero(buf));
/* Test mem_is_zero */
memset(buf,0,128);
buf[128] = 'x';
- test_assert(tor_mem_is_zero(buf, 10));
- test_assert(tor_mem_is_zero(buf, 20));
- test_assert(tor_mem_is_zero(buf, 128));
- test_assert(!tor_mem_is_zero(buf, 129));
+ tt_assert(tor_mem_is_zero(buf, 10));
+ tt_assert(tor_mem_is_zero(buf, 20));
+ tt_assert(tor_mem_is_zero(buf, 128));
+ tt_assert(!tor_mem_is_zero(buf, 129));
buf[60] = (char)255;
- test_assert(!tor_mem_is_zero(buf, 128));
+ tt_assert(!tor_mem_is_zero(buf, 128));
buf[0] = (char)1;
- test_assert(!tor_mem_is_zero(buf, 10));
+ tt_assert(!tor_mem_is_zero(buf, 10));
/* Test 'escaped' */
- test_assert(NULL == escaped(NULL));
- test_streq("\"\"", escaped(""));
- test_streq("\"abcd\"", escaped("abcd"));
- test_streq("\"\\\\ \\n\\r\\t\\\"\\'\"", escaped("\\ \n\r\t\"'"));
- test_streq("\"unnecessary \\'backslashes\\'\"",
+ tt_assert(NULL == escaped(NULL));
+ tt_str_op("\"\"",==, escaped(""));
+ tt_str_op("\"abcd\"",==, escaped("abcd"));
+ tt_str_op("\"\\\\ \\n\\r\\t\\\"\\'\"",==, escaped("\\ \n\r\t\"'"));
+ tt_str_op("\"unnecessary \\'backslashes\\'\"",==,
escaped("unnecessary \'backslashes\'"));
/* Non-printable characters appear as octal */
- test_streq("\"z\\001abc\\277d\"", escaped("z\001abc\277d"));
- test_streq("\"z\\336\\255 ;foo\"", escaped("z\xde\xad\x20;foo"));
+ tt_str_op("\"z\\001abc\\277d\"",==, escaped("z\001abc\277d"));
+ tt_str_op("\"z\\336\\255 ;foo\"",==, escaped("z\xde\xad\x20;foo"));
/* Test strndup and memdup */
{
const char *s = "abcdefghijklmnopqrstuvwxyz";
cp_tmp = tor_strndup(s, 30);
- test_streq(cp_tmp, s); /* same string, */
- test_neq_ptr(cp_tmp, s); /* but different pointers. */
+ tt_str_op(cp_tmp,==, s); /* same string, */
+ tt_ptr_op(cp_tmp,!=,s); /* but different pointers. */
tor_free(cp_tmp);
cp_tmp = tor_strndup(s, 5);
- test_streq(cp_tmp, "abcde");
+ tt_str_op(cp_tmp,==, "abcde");
tor_free(cp_tmp);
s = "a\0b\0c\0d\0e\0";
cp_tmp = tor_memdup(s,10);
- test_memeq(cp_tmp, s, 10); /* same ram, */
- test_neq_ptr(cp_tmp, s); /* but different pointers. */
+ tt_mem_op(cp_tmp,==, s, 10); /* same ram, */
+ tt_ptr_op(cp_tmp,!=,s); /* but different pointers. */
tor_free(cp_tmp);
}
/* Test str-foo functions */
cp_tmp = tor_strdup("abcdef");
- test_assert(tor_strisnonupper(cp_tmp));
+ tt_assert(tor_strisnonupper(cp_tmp));
cp_tmp[3] = 'D';
- test_assert(!tor_strisnonupper(cp_tmp));
+ tt_assert(!tor_strisnonupper(cp_tmp));
tor_strupper(cp_tmp);
- test_streq(cp_tmp, "ABCDEF");
+ tt_str_op(cp_tmp,==, "ABCDEF");
tor_strlower(cp_tmp);
- test_streq(cp_tmp, "abcdef");
- test_assert(tor_strisnonupper(cp_tmp));
- test_assert(tor_strisprint(cp_tmp));
+ tt_str_op(cp_tmp,==, "abcdef");
+ tt_assert(tor_strisnonupper(cp_tmp));
+ tt_assert(tor_strisprint(cp_tmp));
cp_tmp[3] = 3;
- test_assert(!tor_strisprint(cp_tmp));
+ tt_assert(!tor_strisprint(cp_tmp));
tor_free(cp_tmp);
/* Test memmem and memstr */
{
const char *haystack = "abcde";
- test_assert(!tor_memmem(haystack, 5, "ef", 2));
- test_eq_ptr(tor_memmem(haystack, 5, "cd", 2), haystack + 2);
- test_eq_ptr(tor_memmem(haystack, 5, "cde", 3), haystack + 2);
- test_assert(!tor_memmem(haystack, 4, "cde", 3));
+ tt_assert(!tor_memmem(haystack, 5, "ef", 2));
+ tt_ptr_op(tor_memmem(haystack, 5, "cd", 2),==, haystack + 2);
+ tt_ptr_op(tor_memmem(haystack, 5, "cde", 3),==, haystack + 2);
+ tt_assert(!tor_memmem(haystack, 4, "cde", 3));
haystack = "ababcad";
- test_eq_ptr(tor_memmem(haystack, 7, "abc", 3), haystack + 2);
- test_eq_ptr(tor_memmem(haystack, 7, "ad", 2), haystack + 5);
- test_eq_ptr(tor_memmem(haystack, 7, "cad", 3), haystack + 4);
- test_assert(!tor_memmem(haystack, 7, "dadad", 5));
- test_assert(!tor_memmem(haystack, 7, "abcdefghij", 10));
+ tt_ptr_op(tor_memmem(haystack, 7, "abc", 3),==, haystack + 2);
+ tt_ptr_op(tor_memmem(haystack, 7, "ad", 2),==, haystack + 5);
+ tt_ptr_op(tor_memmem(haystack, 7, "cad", 3),==, haystack + 4);
+ tt_assert(!tor_memmem(haystack, 7, "dadad", 5));
+ tt_assert(!tor_memmem(haystack, 7, "abcdefghij", 10));
/* memstr */
- test_eq_ptr(tor_memstr(haystack, 7, "abc"), haystack + 2);
- test_eq_ptr(tor_memstr(haystack, 7, "cad"), haystack + 4);
- test_assert(!tor_memstr(haystack, 6, "cad"));
- test_assert(!tor_memstr(haystack, 7, "cadd"));
- test_assert(!tor_memstr(haystack, 7, "fe"));
- test_assert(!tor_memstr(haystack, 7, "ababcade"));
+ tt_ptr_op(tor_memstr(haystack, 7, "abc"),==, haystack + 2);
+ tt_ptr_op(tor_memstr(haystack, 7, "cad"),==, haystack + 4);
+ tt_assert(!tor_memstr(haystack, 6, "cad"));
+ tt_assert(!tor_memstr(haystack, 7, "cadd"));
+ tt_assert(!tor_memstr(haystack, 7, "fe"));
+ tt_assert(!tor_memstr(haystack, 7, "ababcade"));
}
/* Test hex_str */
@@ -1256,19 +1515,20 @@ test_util_strmisc(void)
size_t i;
for (i = 0; i < sizeof(binary_data); ++i)
binary_data[i] = i;
- test_streq(hex_str(binary_data, 0), "");
- test_streq(hex_str(binary_data, 1), "00");
- test_streq(hex_str(binary_data, 17), "000102030405060708090A0B0C0D0E0F10");
- test_streq(hex_str(binary_data, 32),
+ tt_str_op(hex_str(binary_data, 0),==, "");
+ tt_str_op(hex_str(binary_data, 1),==, "00");
+ tt_str_op(hex_str(binary_data, 17),==,
+ "000102030405060708090A0B0C0D0E0F10");
+ tt_str_op(hex_str(binary_data, 32),==,
"000102030405060708090A0B0C0D0E0F"
"101112131415161718191A1B1C1D1E1F");
- test_streq(hex_str(binary_data, 34),
+ tt_str_op(hex_str(binary_data, 34),==,
"000102030405060708090A0B0C0D0E0F"
"101112131415161718191A1B1C1D1E1F");
/* Repeat these tests for shorter strings after longer strings
have been tried, to make sure we're correctly terminating strings */
- test_streq(hex_str(binary_data, 1), "00");
- test_streq(hex_str(binary_data, 0), "");
+ tt_str_op(hex_str(binary_data, 1),==, "00");
+ tt_str_op(hex_str(binary_data, 0),==, "");
}
/* Test strcmp_opt */
@@ -1297,20 +1557,21 @@ test_util_strmisc(void)
}
static void
-test_util_pow2(void)
+test_util_pow2(void *arg)
{
/* Test tor_log2(). */
- test_eq(tor_log2(64), 6);
- test_eq(tor_log2(65), 6);
- test_eq(tor_log2(63), 5);
- test_eq(tor_log2(0), 0); /* incorrect mathematically, but as specified */
- test_eq(tor_log2(1), 0);
- test_eq(tor_log2(2), 1);
- test_eq(tor_log2(3), 1);
- test_eq(tor_log2(4), 2);
- test_eq(tor_log2(5), 2);
- test_eq(tor_log2(U64_LITERAL(40000000000000000)), 55);
- test_eq(tor_log2(UINT64_MAX), 63);
+ (void)arg;
+ tt_int_op(tor_log2(64),==, 6);
+ tt_int_op(tor_log2(65),==, 6);
+ tt_int_op(tor_log2(63),==, 5);
+ tt_int_op(tor_log2(0),==, 0);/* incorrect mathematically, but as specified */
+ tt_int_op(tor_log2(1),==, 0);
+ tt_int_op(tor_log2(2),==, 1);
+ tt_int_op(tor_log2(3),==, 1);
+ tt_int_op(tor_log2(4),==, 2);
+ tt_int_op(tor_log2(5),==, 2);
+ tt_int_op(tor_log2(U64_LITERAL(40000000000000000)),==, 55);
+ tt_int_op(tor_log2(UINT64_MAX),==, 63);
/* Test round_to_power_of_2 */
tt_u64_op(round_to_power_of_2(120), ==, 128);
@@ -1395,7 +1656,7 @@ thread_test_func_(void* _s)
/** Run unit tests for threading logic. */
static void
-test_util_threads(void)
+test_util_threads(void *arg)
{
char *s1 = NULL, *s2 = NULL;
int done = 0, timedout = 0;
@@ -1405,6 +1666,7 @@ test_util_threads(void)
tv.tv_sec=0;
tv.tv_usec=100*1000;
#endif
+ (void)arg;
thread_test_mutex_ = tor_mutex_new();
thread_test_start1_ = tor_mutex_new();
thread_test_start2_ = tor_mutex_new();
@@ -1442,15 +1704,15 @@ test_util_threads(void)
if (timedout) {
printf("\nTimed out: %d %d", t1_count, t2_count);
- test_assert(strmap_get(thread_test_strmap_, "thread 1"));
- test_assert(strmap_get(thread_test_strmap_, "thread 2"));
- test_assert(!timedout);
+ tt_assert(strmap_get(thread_test_strmap_, "thread 1"));
+ tt_assert(strmap_get(thread_test_strmap_, "thread 2"));
+ tt_assert(!timedout);
}
/* different thread IDs. */
- test_assert(strcmp(strmap_get(thread_test_strmap_, "thread 1"),
+ tt_assert(strcmp(strmap_get(thread_test_strmap_, "thread 1"),
strmap_get(thread_test_strmap_, "thread 2")));
- test_assert(!strcmp(strmap_get(thread_test_strmap_, "thread 1"),
+ tt_assert(!strcmp(strmap_get(thread_test_strmap_, "thread 1"),
strmap_get(thread_test_strmap_, "last to run")) ||
!strcmp(strmap_get(thread_test_strmap_, "thread 2"),
strmap_get(thread_test_strmap_, "last to run")));
@@ -1470,51 +1732,52 @@ test_util_threads(void)
/** Run unit tests for compression functions */
static void
-test_util_gzip(void)
+test_util_gzip(void *arg)
{
char *buf1=NULL, *buf2=NULL, *buf3=NULL, *cp1, *cp2;
const char *ccp2;
size_t len1, len2;
tor_zlib_state_t *state = NULL;
+ (void)arg;
buf1 = tor_strdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ");
- test_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
+ tt_assert(detect_compression_method(buf1, strlen(buf1)) == UNKNOWN_METHOD);
if (is_gzip_supported()) {
- test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
+ tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
GZIP_METHOD));
- test_assert(buf2);
- test_assert(len1 < strlen(buf1));
- test_assert(detect_compression_method(buf2, len1) == GZIP_METHOD);
+ tt_assert(buf2);
+ tt_assert(len1 < strlen(buf1));
+ tt_assert(detect_compression_method(buf2, len1) == GZIP_METHOD);
- test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
+ tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
GZIP_METHOD, 1, LOG_INFO));
- test_assert(buf3);
- test_eq(strlen(buf1) + 1, len2);
- test_streq(buf1, buf3);
+ tt_assert(buf3);
+ tt_int_op(strlen(buf1) + 1,==, len2);
+ tt_str_op(buf1,==, buf3);
tor_free(buf2);
tor_free(buf3);
}
- test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
+ tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
ZLIB_METHOD));
- test_assert(buf2);
- test_assert(detect_compression_method(buf2, len1) == ZLIB_METHOD);
+ tt_assert(buf2);
+ tt_assert(detect_compression_method(buf2, len1) == ZLIB_METHOD);
- test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
+ tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1,
ZLIB_METHOD, 1, LOG_INFO));
- test_assert(buf3);
- test_eq(strlen(buf1) + 1, len2);
- test_streq(buf1, buf3);
+ tt_assert(buf3);
+ tt_int_op(strlen(buf1) + 1,==, len2);
+ tt_str_op(buf1,==, buf3);
/* Check whether we can uncompress concatenated, compressed strings. */
tor_free(buf3);
buf2 = tor_reallocarray(buf2, len1, 2);
memcpy(buf2+len1, buf2, len1);
- test_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2,
+ tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1*2,
ZLIB_METHOD, 1, LOG_INFO));
- test_eq((strlen(buf1)+1)*2, len2);
- test_memeq(buf3,
+ tt_int_op((strlen(buf1)+1)*2,==, len2);
+ tt_mem_op(buf3,==,
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAAAAAAAAAAAAAAAAAZ\0",
(strlen(buf1)+1)*2);
@@ -1526,7 +1789,7 @@ test_util_gzip(void)
/* Check whether we can uncompress partial strings. */
buf1 =
tor_strdup("String with low redundancy that won't be compressed much.");
- test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
+ tt_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
ZLIB_METHOD));
tt_assert(len1>16);
/* when we allow an incomplete string, we should succeed.*/
@@ -1552,22 +1815,22 @@ test_util_gzip(void)
len1 = 1024;
ccp2 = "ABCDEFGHIJABCDEFGHIJ";
len2 = 21;
- test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 0)
+ tt_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 0)
== TOR_ZLIB_OK);
- test_eq(0, len2); /* Make sure we compressed it all. */
- test_assert(cp1 > buf1);
+ tt_int_op(0,==, len2); /* Make sure we compressed it all. */
+ tt_assert(cp1 > buf1);
len2 = 0;
cp2 = cp1;
- test_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 1)
+ tt_assert(tor_zlib_process(state, &cp1, &len1, &ccp2, &len2, 1)
== TOR_ZLIB_DONE);
- test_eq(0, len2);
- test_assert(cp1 > cp2); /* Make sure we really added something. */
+ tt_int_op(0,==, len2);
+ tt_assert(cp1 > cp2); /* Make sure we really added something. */
tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
ZLIB_METHOD, 1, LOG_WARN));
- test_streq(buf3, "ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/
- test_eq(21, len2);
+ tt_str_op(buf3,==,"ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/
+ tt_int_op(21,==, len2);
done:
if (state)
@@ -1579,7 +1842,7 @@ test_util_gzip(void)
/** Run unit tests for mmap() wrapper functionality. */
static void
-test_util_mmap(void)
+test_util_mmap(void *arg)
{
char *fname1 = tor_strdup(get_fname("mapped_1"));
char *fname2 = tor_strdup(get_fname("mapped_2"));
@@ -1588,25 +1851,26 @@ test_util_mmap(void)
char *buf = tor_malloc(17000);
tor_mmap_t *mapping = NULL;
+ (void)arg;
crypto_rand(buf, buflen);
mapping = tor_mmap_file(fname1);
- test_assert(! mapping);
+ tt_assert(! mapping);
write_str_to_file(fname1, "Short file.", 1);
mapping = tor_mmap_file(fname1);
- test_assert(mapping);
- test_eq(mapping->size, strlen("Short file."));
- test_streq(mapping->data, "Short file.");
+ tt_assert(mapping);
+ tt_int_op(mapping->size,==, strlen("Short file."));
+ tt_str_op(mapping->data,==, "Short file.");
#ifdef _WIN32
tt_int_op(0, ==, tor_munmap_file(mapping));
mapping = NULL;
- test_assert(unlink(fname1) == 0);
+ tt_assert(unlink(fname1) == 0);
#else
/* make sure we can unlink. */
- test_assert(unlink(fname1) == 0);
- test_streq(mapping->data, "Short file.");
+ tt_assert(unlink(fname1) == 0);
+ tt_str_op(mapping->data,==, "Short file.");
tt_int_op(0, ==, tor_munmap_file(mapping));
mapping = NULL;
#endif
@@ -1614,29 +1878,29 @@ test_util_mmap(void)
/* Now a zero-length file. */
write_str_to_file(fname1, "", 1);
mapping = tor_mmap_file(fname1);
- test_eq_ptr(mapping, NULL);
- test_eq(ERANGE, errno);
+ tt_ptr_op(mapping,==, NULL);
+ tt_int_op(ERANGE,==, errno);
unlink(fname1);
/* Make sure that we fail to map a no-longer-existent file. */
mapping = tor_mmap_file(fname1);
- test_assert(! mapping);
+ tt_assert(! mapping);
/* Now try a big file that stretches across a few pages and isn't aligned */
write_bytes_to_file(fname2, buf, buflen, 1);
mapping = tor_mmap_file(fname2);
- test_assert(mapping);
- test_eq(mapping->size, buflen);
- test_memeq(mapping->data, buf, buflen);
+ tt_assert(mapping);
+ tt_int_op(mapping->size,==, buflen);
+ tt_mem_op(mapping->data,==, buf, buflen);
tt_int_op(0, ==, tor_munmap_file(mapping));
mapping = NULL;
/* Now try a big aligned file. */
write_bytes_to_file(fname3, buf, 16384, 1);
mapping = tor_mmap_file(fname3);
- test_assert(mapping);
- test_eq(mapping->size, 16384);
- test_memeq(mapping->data, buf, 16384);
+ tt_assert(mapping);
+ tt_int_op(mapping->size,==, 16384);
+ tt_mem_op(mapping->data,==, buf, 16384);
tt_int_op(0, ==, tor_munmap_file(mapping));
mapping = NULL;
@@ -1655,17 +1919,18 @@ test_util_mmap(void)
/** Run unit tests for escaping/unescaping data for use by controllers. */
static void
-test_util_control_formats(void)
+test_util_control_formats(void *arg)
{
char *out = NULL;
const char *inp =
"..This is a test\r\n.of the emergency \n..system.\r\n\rZ.\r\n";
size_t sz;
+ (void)arg;
sz = read_escaped_data(inp, strlen(inp), &out);
- test_streq(out,
+ tt_str_op(out,==,
".This is a test\nof the emergency \n.system.\n\rZ.\n");
- test_eq(sz, strlen(out));
+ tt_int_op(sz,==, strlen(out));
done:
tor_free(out);
@@ -1685,9 +1950,10 @@ test_util_control_formats(void)
} while (0)
static void
-test_util_sscanf(void)
+test_util_sscanf(void *arg)
{
unsigned u1, u2, u3;
+ unsigned long ulng;
char s1[20], s2[10], s3[10], ch;
int r;
long lng1,lng2;
@@ -1695,186 +1961,335 @@ test_util_sscanf(void)
double d1,d2,d3,d4;
/* Simple tests (malformed patterns, literal matching, ...) */
- test_eq(-1, tor_sscanf("123", "%i", &r)); /* %i is not supported */
- test_eq(-1, tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */
- test_eq(-1, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */
- test_eq(-1, tor_sscanf("prettylongstring", "%999999s", s1));
+ (void)arg;
+ tt_int_op(-1,==, tor_sscanf("123", "%i", &r)); /* %i is not supported */
+ tt_int_op(-1,==,
+ tor_sscanf("wrong", "%5c", s1)); /* %c cannot have a number. */
+ tt_int_op(-1,==, tor_sscanf("hello", "%s", s1)); /* %s needs a number. */
+ tt_int_op(-1,==, tor_sscanf("prettylongstring", "%999999s", s1));
#if 0
/* GCC thinks these two are illegal. */
test_eq(-1, tor_sscanf("prettylongstring", "%0s", s1));
test_eq(0, tor_sscanf("prettylongstring", "%10s", NULL));
#endif
/* No '%'-strings: always "success" */
- test_eq(0, tor_sscanf("hello world", "hello world"));
- test_eq(0, tor_sscanf("hello world", "good bye"));
+ tt_int_op(0,==, tor_sscanf("hello world", "hello world"));
+ tt_int_op(0,==, tor_sscanf("hello world", "good bye"));
/* Excess data */
- test_eq(0, tor_sscanf("hello 3", "%u", &u1)); /* have to match the start */
- test_eq(0, tor_sscanf(" 3 hello", "%u", &u1));
- test_eq(0, tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */
- test_eq(1, tor_sscanf("3 hello", "%u", &u1)); /* but trailing is alright */
+ tt_int_op(0,==,
+ tor_sscanf("hello 3", "%u", &u1)); /* have to match the start */
+ tt_int_op(0,==, tor_sscanf(" 3 hello", "%u", &u1));
+ tt_int_op(0,==,
+ tor_sscanf(" 3 hello", "%2u", &u1)); /* not even in this case */
+ tt_int_op(1,==,
+ tor_sscanf("3 hello", "%u", &u1)); /* but trailing is alright */
/* Numbers (ie. %u) */
- test_eq(0, tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */
- test_eq(1, tor_sscanf("12345", "%u", &u1));
- test_eq(12345u, u1);
- test_eq(1, tor_sscanf("12346 ", "%u", &u1));
- test_eq(12346u, u1);
- test_eq(0, tor_sscanf(" 12347", "%u", &u1));
- test_eq(1, tor_sscanf(" 12348", " %u", &u1));
- test_eq(12348u, u1);
- test_eq(1, tor_sscanf("0", "%u", &u1));
- test_eq(0u, u1);
- test_eq(1, tor_sscanf("0000", "%u", &u2));
- test_eq(0u, u2);
- test_eq(0, tor_sscanf("", "%u", &u1)); /* absent number */
- test_eq(0, tor_sscanf("A", "%u", &u1)); /* bogus number */
- test_eq(0, tor_sscanf("-1", "%u", &u1)); /* negative number */
- test_eq(1, tor_sscanf("4294967295", "%u", &u1)); /* UINT32_MAX should work */
- test_eq(4294967295u, u1);
- test_eq(0, tor_sscanf("4294967296", "%u", &u1)); /* But not at 32 bits */
- test_eq(1, tor_sscanf("4294967296", "%9u", &u1)); /* but parsing only 9... */
- test_eq(429496729u, u1);
+ tt_int_op(0,==,
+ tor_sscanf("hello world 3", "hello worlb %u", &u1)); /* d vs b */
+ tt_int_op(1,==, tor_sscanf("12345", "%u", &u1));
+ tt_int_op(12345u,==, u1);
+ tt_int_op(1,==, tor_sscanf("12346 ", "%u", &u1));
+ tt_int_op(12346u,==, u1);
+ tt_int_op(0,==, tor_sscanf(" 12347", "%u", &u1));
+ tt_int_op(1,==, tor_sscanf(" 12348", " %u", &u1));
+ tt_int_op(12348u,==, u1);
+ tt_int_op(1,==, tor_sscanf("0", "%u", &u1));
+ tt_int_op(0u,==, u1);
+ tt_int_op(1,==, tor_sscanf("0000", "%u", &u2));
+ tt_int_op(0u,==, u2);
+ tt_int_op(0,==, tor_sscanf("", "%u", &u1)); /* absent number */
+ tt_int_op(0,==, tor_sscanf("A", "%u", &u1)); /* bogus number */
+ tt_int_op(0,==, tor_sscanf("-1", "%u", &u1)); /* negative number */
/* Numbers with size (eg. %2u) */
- test_eq(0, tor_sscanf("-1", "%2u", &u1));
- test_eq(2, tor_sscanf("123456", "%2u%u", &u1, &u2));
- test_eq(12u, u1);
- test_eq(3456u, u2);
- test_eq(1, tor_sscanf("123456", "%8u", &u1));
- test_eq(123456u, u1);
- test_eq(1, tor_sscanf("123457 ", "%8u", &u1));
- test_eq(123457u, u1);
- test_eq(0, tor_sscanf(" 123456", "%8u", &u1));
- test_eq(3, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3));
- test_eq(12u, u1);
- test_eq(3u, u2);
- test_eq(456u, u3);
- test_eq(3, tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */
- test_eq(67u, u1);
- test_eq(8u, u2);
- test_eq(99u, u3);
+ tt_int_op(0,==, tor_sscanf("-1", "%2u", &u1));
+ tt_int_op(2,==, tor_sscanf("123456", "%2u%u", &u1, &u2));
+ tt_int_op(12u,==, u1);
+ tt_int_op(3456u,==, u2);
+ tt_int_op(1,==, tor_sscanf("123456", "%8u", &u1));
+ tt_int_op(123456u,==, u1);
+ tt_int_op(1,==, tor_sscanf("123457 ", "%8u", &u1));
+ tt_int_op(123457u,==, u1);
+ tt_int_op(0,==, tor_sscanf(" 123456", "%8u", &u1));
+ tt_int_op(3,==, tor_sscanf("!12:3:456", "!%2u:%2u:%3u", &u1, &u2, &u3));
+ tt_int_op(12u,==, u1);
+ tt_int_op(3u,==, u2);
+ tt_int_op(456u,==, u3);
+ tt_int_op(3,==,
+ tor_sscanf("67:8:099", "%2u:%2u:%3u", &u1, &u2, &u3)); /* 0s */
+ tt_int_op(67u,==, u1);
+ tt_int_op(8u,==, u2);
+ tt_int_op(99u,==, u3);
/* %u does not match space.*/
- test_eq(2, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3));
- test_eq(12u, u1);
- test_eq(3u, u2);
+ tt_int_op(2,==, tor_sscanf("12:3: 45", "%2u:%2u:%3u", &u1, &u2, &u3));
+ tt_int_op(12u,==, u1);
+ tt_int_op(3u,==, u2);
/* %u does not match negative numbers. */
- test_eq(2, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3));
- test_eq(67u, u1);
- test_eq(8u, u2);
+ tt_int_op(2,==, tor_sscanf("67:8:-9", "%2u:%2u:%3u", &u1, &u2, &u3));
+ tt_int_op(67u,==, u1);
+ tt_int_op(8u,==, u2);
/* Arbitrary amounts of 0-padding are okay */
- test_eq(3, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u",
+ tt_int_op(3,==, tor_sscanf("12:03:000000000000000099", "%2u:%2u:%u",
&u1, &u2, &u3));
- test_eq(12u, u1);
- test_eq(3u, u2);
- test_eq(99u, u3);
+ tt_int_op(12u,==, u1);
+ tt_int_op(3u,==, u2);
+ tt_int_op(99u,==, u3);
/* Hex (ie. %x) */
- test_eq(3, tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3));
- test_eq(0x1234, u1);
- test_eq(0x2ABCDEF, u2);
- test_eq(0xFF, u3);
+ tt_int_op(3,==, tor_sscanf("1234 02aBcdEf ff", "%x %x %x", &u1, &u2, &u3));
+ tt_int_op(0x1234,==, u1);
+ tt_int_op(0x2ABCDEF,==, u2);
+ tt_int_op(0xFF,==, u3);
/* Width works on %x */
- test_eq(3, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3));
- test_eq(0xf00d, u1);
- test_eq(0xcafe, u2);
- test_eq(444, u3);
+ tt_int_op(3,==, tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3));
+ tt_int_op(0xf00d,==, u1);
+ tt_int_op(0xcafe,==, u2);
+ tt_int_op(444,==, u3);
/* Literal '%' (ie. '%%') */
- test_eq(1, tor_sscanf("99% fresh", "%3u%% fresh", &u1));
- test_eq(99, u1);
- test_eq(0, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1));
- test_eq(1, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1));
- test_eq(2, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1));
- test_eq(99, u1);
- test_streq(s1, "fresh");
- test_eq(1, tor_sscanf("% boo", "%% %3s", s1));
- test_streq("boo", s1);
+ tt_int_op(1,==, tor_sscanf("99% fresh", "%3u%% fresh", &u1));
+ tt_int_op(99,==, u1);
+ tt_int_op(0,==, tor_sscanf("99 fresh", "%% %3u %s", &u1, s1));
+ tt_int_op(1,==, tor_sscanf("99 fresh", "%3u%% %s", &u1, s1));
+ tt_int_op(2,==, tor_sscanf("99 fresh", "%3u %5s %%", &u1, s1));
+ tt_int_op(99,==, u1);
+ tt_str_op(s1,==, "fresh");
+ tt_int_op(1,==, tor_sscanf("% boo", "%% %3s", s1));
+ tt_str_op("boo",==, s1);
/* Strings (ie. %s) */
- test_eq(2, tor_sscanf("hello", "%3s%7s", s1, s2));
- test_streq(s1, "hel");
- test_streq(s2, "lo");
- test_eq(2, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */
- test_streq(s3, "WD");
- test_eq(40, u1);
- test_eq(2, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */
- test_streq(s3, "WD4");
- test_eq(0, u1);
- test_eq(2, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */
- test_eq(76, u1);
- test_streq(s1, "trombones");
- test_eq(1, tor_sscanf("prettylongstring", "%999s", s1));
- test_streq(s1, "prettylongstring");
+ tt_int_op(2,==, tor_sscanf("hello", "%3s%7s", s1, s2));
+ tt_str_op(s1,==, "hel");
+ tt_str_op(s2,==, "lo");
+ tt_int_op(2,==, tor_sscanf("WD40", "%2s%u", s3, &u1)); /* %s%u */
+ tt_str_op(s3,==, "WD");
+ tt_int_op(40,==, u1);
+ tt_int_op(2,==, tor_sscanf("WD40", "%3s%u", s3, &u1)); /* %s%u */
+ tt_str_op(s3,==, "WD4");
+ tt_int_op(0,==, u1);
+ tt_int_op(2,==, tor_sscanf("76trombones", "%6u%9s", &u1, s1)); /* %u%s */
+ tt_int_op(76,==, u1);
+ tt_str_op(s1,==, "trombones");
+ tt_int_op(1,==, tor_sscanf("prettylongstring", "%999s", s1));
+ tt_str_op(s1,==, "prettylongstring");
/* %s doesn't eat spaces */
- test_eq(2, tor_sscanf("hello world", "%9s %9s", s1, s2));
- test_streq(s1, "hello");
- test_streq(s2, "world");
- test_eq(2, tor_sscanf("bye world?", "%9s %9s", s1, s2));
- test_streq(s1, "bye");
- test_streq(s2, "");
- test_eq(3, tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */
- test_streq(s1, "hi");
- test_streq(s2, "");
- test_streq(s3, "");
-
- test_eq(3, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
- test_eq(4, tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
- test_eq(' ', ch);
+ tt_int_op(2,==, tor_sscanf("hello world", "%9s %9s", s1, s2));
+ tt_str_op(s1,==, "hello");
+ tt_str_op(s2,==, "world");
+ tt_int_op(2,==, tor_sscanf("bye world?", "%9s %9s", s1, s2));
+ tt_str_op(s1,==, "bye");
+ tt_str_op(s2,==, "");
+ tt_int_op(3,==,
+ tor_sscanf("hi", "%9s%9s%3s", s1, s2, s3)); /* %s can be empty. */
+ tt_str_op(s1,==, "hi");
+ tt_str_op(s2,==, "");
+ tt_str_op(s3,==, "");
+
+ tt_int_op(3,==, tor_sscanf("1.2.3", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
+ tt_int_op(4,==,
+ tor_sscanf("1.2.3 foobar", "%u.%u.%u%c", &u1, &u2, &u3, &ch));
+ tt_int_op(' ',==, ch);
r = tor_sscanf("12345 -67890 -1", "%d %ld %d", &int1, &lng1, &int2);
- test_eq(r,3);
- test_eq(int1, 12345);
- test_eq(lng1, -67890);
- test_eq(int2, -1);
+ tt_int_op(r,==, 3);
+ tt_int_op(int1,==, 12345);
+ tt_int_op(lng1,==, -67890);
+ tt_int_op(int2,==, -1);
#if SIZEOF_INT == 4
+ /* %u */
+ /* UINT32_MAX should work */
+ tt_int_op(1,==, tor_sscanf("4294967295", "%u", &u1));
+ tt_int_op(4294967295U,==, u1);
+
+ /* But UINT32_MAX + 1 shouldn't work */
+ tt_int_op(0,==, tor_sscanf("4294967296", "%u", &u1));
+ /* but parsing only 9... */
+ tt_int_op(1,==, tor_sscanf("4294967296", "%9u", &u1));
+ tt_int_op(429496729U,==, u1);
+
+ /* %x */
+ /* UINT32_MAX should work */
+ tt_int_op(1,==, tor_sscanf("FFFFFFFF", "%x", &u1));
+ tt_int_op(0xFFFFFFFF,==, u1);
+
+ /* But UINT32_MAX + 1 shouldn't work */
+ tt_int_op(0,==, tor_sscanf("100000000", "%x", &u1));
+
+ /* %d */
+ /* INT32_MIN and INT32_MAX should work */
r = tor_sscanf("-2147483648. 2147483647.", "%d. %d.", &int1, &int2);
- test_eq(r,2);
- test_eq(int1, -2147483647-1);
- test_eq(int2, 2147483647);
+ tt_int_op(r,==, 2);
+ tt_int_op(int1,==, -2147483647 - 1);
+ tt_int_op(int2,==, 2147483647);
+
+ /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
+ r = tor_sscanf("-2147483649.", "%d.", &int1);
+ tt_int_op(r,==, 0);
- r = tor_sscanf("-2147483679.", "%d.", &int1);
- test_eq(r,0);
+ r = tor_sscanf("2147483648.", "%d.", &int1);
+ tt_int_op(r,==, 0);
- r = tor_sscanf("2147483678.", "%d.", &int1);
- test_eq(r,0);
+ /* and the first failure stops further processing */
+ r = tor_sscanf("-2147483648. 2147483648.",
+ "%d. %d.", &int1, &int2);
+ tt_int_op(r,==, 1);
+
+ r = tor_sscanf("-2147483649. 2147483647.",
+ "%d. %d.", &int1, &int2);
+ tt_int_op(r,==, 0);
+
+ r = tor_sscanf("2147483648. -2147483649.",
+ "%d. %d.", &int1, &int2);
+ tt_int_op(r,==, 0);
#elif SIZEOF_INT == 8
+ /* %u */
+ /* UINT64_MAX should work */
+ tt_int_op(1,==, tor_sscanf("18446744073709551615", "%u", &u1));
+ tt_int_op(18446744073709551615U,==, u1);
+
+ /* But UINT64_MAX + 1 shouldn't work */
+ tt_int_op(0,==, tor_sscanf("18446744073709551616", "%u", &u1));
+ /* but parsing only 19... */
+ tt_int_op(1,==, tor_sscanf("18446744073709551616", "%19u", &u1));
+ tt_int_op(1844674407370955161U,==, u1);
+
+ /* %x */
+ /* UINT64_MAX should work */
+ tt_int_op(1,==, tor_sscanf("FFFFFFFFFFFFFFFF", "%x", &u1));
+ tt_int_op(0xFFFFFFFFFFFFFFFF,==, u1);
+
+ /* But UINT64_MAX + 1 shouldn't work */
+ tt_int_op(0,==, tor_sscanf("10000000000000000", "%x", &u1));
+
+ /* %d */
+ /* INT64_MIN and INT64_MAX should work */
r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
"%d. %d.", &int1, &int2);
- test_eq(r,2);
- test_eq(int1, -9223372036854775807-1);
- test_eq(int2, 9223372036854775807);
+ tt_int_op(r,==, 2);
+ tt_int_op(int1,==, -9223372036854775807 - 1);
+ tt_int_op(int2,==, 9223372036854775807);
+ /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
r = tor_sscanf("-9223372036854775809.", "%d.", &int1);
- test_eq(r,0);
+ tt_int_op(r,==, 0);
r = tor_sscanf("9223372036854775808.", "%d.", &int1);
- test_eq(r,0);
+ tt_int_op(r,==, 0);
+
+ /* and the first failure stops further processing */
+ r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
+ "%d. %d.", &int1, &int2);
+ tt_int_op(r,==, 1);
+
+ r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
+ "%d. %d.", &int1, &int2);
+ tt_int_op(r,==, 0);
+
+ r = tor_sscanf("9223372036854775808. -9223372036854775809.",
+ "%d. %d.", &int1, &int2);
+ tt_int_op(r,==, 0);
#endif
#if SIZEOF_LONG == 4
+ /* %lu */
+ /* UINT32_MAX should work */
+ tt_int_op(1,==, tor_sscanf("4294967295", "%lu", &ulng));
+ tt_int_op(4294967295UL,==, ulng);
+
+ /* But UINT32_MAX + 1 shouldn't work */
+ tt_int_op(0,==, tor_sscanf("4294967296", "%lu", &ulng));
+ /* but parsing only 9... */
+ tt_int_op(1,==, tor_sscanf("4294967296", "%9lu", &ulng));
+ tt_int_op(429496729UL,==, ulng);
+
+ /* %lx */
+ /* UINT32_MAX should work */
+ tt_int_op(1,==, tor_sscanf("FFFFFFFF", "%lx", &ulng));
+ tt_int_op(0xFFFFFFFFUL,==, ulng);
+
+ /* But UINT32_MAX + 1 shouldn't work */
+ tt_int_op(0,==, tor_sscanf("100000000", "%lx", &ulng));
+
+ /* %ld */
+ /* INT32_MIN and INT32_MAX should work */
r = tor_sscanf("-2147483648. 2147483647.", "%ld. %ld.", &lng1, &lng2);
- test_eq(r,2);
- test_eq(lng1, -2147483647 - 1);
- test_eq(lng2, 2147483647);
+ tt_int_op(r,==, 2);
+ tt_int_op(lng1,==, -2147483647L - 1L);
+ tt_int_op(lng2,==, 2147483647L);
+
+ /* But INT32_MIN - 1 and INT32_MAX + 1 shouldn't work */
+ r = tor_sscanf("-2147483649.", "%ld.", &lng1);
+ tt_int_op(r,==, 0);
+
+ r = tor_sscanf("2147483648.", "%ld.", &lng1);
+ tt_int_op(r,==, 0);
+
+ /* and the first failure stops further processing */
+ r = tor_sscanf("-2147483648. 2147483648.",
+ "%ld. %ld.", &lng1, &lng2);
+ tt_int_op(r,==, 1);
+
+ r = tor_sscanf("-2147483649. 2147483647.",
+ "%ld. %ld.", &lng1, &lng2);
+ tt_int_op(r,==, 0);
+
+ r = tor_sscanf("2147483648. -2147483649.",
+ "%ld. %ld.", &lng1, &lng2);
+ tt_int_op(r,==, 0);
#elif SIZEOF_LONG == 8
+ /* %lu */
+ /* UINT64_MAX should work */
+ tt_int_op(1,==, tor_sscanf("18446744073709551615", "%lu", &ulng));
+ tt_int_op(18446744073709551615UL,==, ulng);
+
+ /* But UINT64_MAX + 1 shouldn't work */
+ tt_int_op(0,==, tor_sscanf("18446744073709551616", "%lu", &ulng));
+ /* but parsing only 19... */
+ tt_int_op(1,==, tor_sscanf("18446744073709551616", "%19lu", &ulng));
+ tt_int_op(1844674407370955161UL,==, ulng);
+
+ /* %lx */
+ /* UINT64_MAX should work */
+ tt_int_op(1,==, tor_sscanf("FFFFFFFFFFFFFFFF", "%lx", &ulng));
+ tt_int_op(0xFFFFFFFFFFFFFFFFUL,==, ulng);
+
+ /* But UINT64_MAX + 1 shouldn't work */
+ tt_int_op(0,==, tor_sscanf("10000000000000000", "%lx", &ulng));
+
+ /* %ld */
+ /* INT64_MIN and INT64_MAX should work */
r = tor_sscanf("-9223372036854775808. 9223372036854775807.",
"%ld. %ld.", &lng1, &lng2);
- test_eq(r,2);
- test_eq(lng1, -9223372036854775807L - 1);
- test_eq(lng2, 9223372036854775807L);
+ tt_int_op(r,==, 2);
+ tt_int_op(lng1,==, -9223372036854775807L - 1L);
+ tt_int_op(lng2,==, 9223372036854775807L);
+
+ /* But INT64_MIN - 1 and INT64_MAX + 1 shouldn't work */
+ r = tor_sscanf("-9223372036854775809.", "%ld.", &lng1);
+ tt_int_op(r,==, 0);
+
+ r = tor_sscanf("9223372036854775808.", "%ld.", &lng1);
+ tt_int_op(r,==, 0);
+ /* and the first failure stops further processing */
r = tor_sscanf("-9223372036854775808. 9223372036854775808.",
"%ld. %ld.", &lng1, &lng2);
- test_eq(r,1);
- r = tor_sscanf("-9223372036854775809. 9223372036854775808.",
+ tt_int_op(r,==, 1);
+
+ r = tor_sscanf("-9223372036854775809. 9223372036854775807.",
+ "%ld. %ld.", &lng1, &lng2);
+ tt_int_op(r,==, 0);
+
+ r = tor_sscanf("9223372036854775808. -9223372036854775809.",
"%ld. %ld.", &lng1, &lng2);
- test_eq(r,0);
+ tt_int_op(r,==, 0);
#endif
r = tor_sscanf("123.456 .000007 -900123123.2000787 00003.2",
"%lf %lf %lf %lf", &d1,&d2,&d3,&d4);
- test_eq(r,4);
+ tt_int_op(r,==, 4);
test_feq(d1, 123.456);
test_feq(d2, .000007);
test_feq(d3, -900123123.2000787);
@@ -1884,34 +2299,466 @@ test_util_sscanf(void)
;
}
+#define tt_char_op(a,op,b) tt_assert_op_type(a,op,b,char,"%c")
+#define tt_ci_char_op(a,op,b) tt_char_op(tolower(a),op,tolower(b))
+
+#ifndef HAVE_STRNLEN
+static size_t
+strnlen(const char *s, size_t len)
+{
+ const char *p = memchr(s, 0, len);
+ if (!p)
+ return len;
+ return p - s;
+}
+#endif
+
static void
-test_util_path_is_relative(void)
+test_util_format_time_interval(void *arg)
+{
+ /* use the same sized buffer and integers as tor uses */
+#define DBUF_SIZE 64
+ char dbuf[DBUF_SIZE];
+#define T_ "%ld"
+ long sec, min, hour, day;
+
+ /* we don't care about the exact spelling of the
+ * second(s), minute(s), hour(s), day(s) labels */
+#define LABEL_SIZE 21
+#define L_ "%20s"
+ char label_s[LABEL_SIZE];
+ char label_m[LABEL_SIZE];
+ char label_h[LABEL_SIZE];
+ char label_d[LABEL_SIZE];
+
+#define TL_ T_ " " L_
+
+ int r;
+
+ (void)arg;
+
+ /* In these tests, we're not picky about
+ * spelling or abbreviations */
+
+ /* seconds: 0, 1, 9, 10, 59 */
+
+ /* ignore exact spelling of "second(s)"*/
+ format_time_interval(dbuf, sizeof(dbuf), 0);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &sec, label_s);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(sec,==, 0);
+
+ format_time_interval(dbuf, sizeof(dbuf), 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &sec, label_s);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(sec,==, 1);
+
+ format_time_interval(dbuf, sizeof(dbuf), 10);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &sec, label_s);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(sec,==, 10);
+
+ format_time_interval(dbuf, sizeof(dbuf), 59);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &sec, label_s);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(sec,==, 59);
+
+ /* negative seconds are reported as their absolute value */
+
+ format_time_interval(dbuf, sizeof(dbuf), -4);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &sec, label_s);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(sec,==, 4);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+
+ format_time_interval(dbuf, sizeof(dbuf), -32);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &sec, label_s);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(sec,==, 32);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+
+ /* minutes: 1:00, 1:01, 1:59, 2:00, 2:01, 59:59 */
+
+ /* ignore trailing "0 second(s)", if present */
+ format_time_interval(dbuf, sizeof(dbuf), 60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &min, label_m);
+ tt_int_op(r,==, 2);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(min,==, 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+
+ /* ignore exact spelling of "minute(s)," and "second(s)" */
+ format_time_interval(dbuf, sizeof(dbuf), 60 + 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &min, label_m, &sec, label_s);
+ tt_int_op(r,==, 4);
+ tt_int_op(min,==, 1);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(sec,==, 1);
+ tt_ci_char_op(label_s[0],==, 's');
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+
+ format_time_interval(dbuf, sizeof(dbuf), 60*2 - 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &min, label_m, &sec, label_s);
+ tt_int_op(r,==, 4);
+ tt_int_op(min,==, 1);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(sec,==, 59);
+ tt_ci_char_op(label_s[0],==, 's');
+
+ /* ignore trailing "0 second(s)", if present */
+ format_time_interval(dbuf, sizeof(dbuf), 60*2);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &min, label_m);
+ tt_int_op(r,==, 2);
+ tt_int_op(min,==, 2);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* ignore exact spelling of "minute(s)," and "second(s)" */
+ format_time_interval(dbuf, sizeof(dbuf), 60*2 + 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &min, label_m, &sec, label_s);
+ tt_int_op(r,==, 4);
+ tt_int_op(min,==, 2);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(sec,==, 1);
+ tt_ci_char_op(label_s[0],==, 's');
+
+ format_time_interval(dbuf, sizeof(dbuf), 60*60 - 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &min, label_m, &sec, label_s);
+ tt_int_op(r,==, 4);
+ tt_int_op(min,==, 59);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(sec,==, 59);
+ tt_ci_char_op(label_s[0],==, 's');
+
+ /* negative minutes are reported as their absolute value */
+
+ /* ignore trailing "0 second(s)", if present */
+ format_time_interval(dbuf, sizeof(dbuf), -3*60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &min, label_m);
+ tt_int_op(r,==, 2);
+ tt_int_op(min,==, 3);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* ignore exact spelling of "minute(s)," and "second(s)" */
+ format_time_interval(dbuf, sizeof(dbuf), -96);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &min, label_m, &sec, label_s);
+ tt_int_op(r,==, 4);
+ tt_int_op(min,==, 1);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(sec,==, 36);
+ tt_ci_char_op(label_s[0],==, 's');
+
+ format_time_interval(dbuf, sizeof(dbuf), -2815);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &min, label_m, &sec, label_s);
+ tt_int_op(r,==, 4);
+ tt_int_op(min,==, 46);
+ tt_ci_char_op(label_m[0],==, 'm');
+ tt_int_op(sec,==, 55);
+ tt_ci_char_op(label_s[0],==, 's');
+
+ /* hours: 1:00, 1:00:01, 1:01, 23:59, 23:59:59 */
+ /* always ignore trailing seconds, if present */
+
+ /* ignore trailing "0 minute(s)" etc., if present */
+ format_time_interval(dbuf, sizeof(dbuf), 60*60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &hour, label_h);
+ tt_int_op(r,==, 2);
+ tt_int_op(hour,==, 1);
+ tt_ci_char_op(label_h[0],==, 'h');
+
+ format_time_interval(dbuf, sizeof(dbuf), 60*60 + 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &hour, label_h);
+ tt_int_op(r,==, 2);
+ tt_int_op(hour,==, 1);
+ tt_ci_char_op(label_h[0],==, 'h');
+
+ /* ignore exact spelling of "hour(s)," etc. */
+ format_time_interval(dbuf, sizeof(dbuf), 60*60 + 60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 4);
+ tt_int_op(hour,==, 1);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 1);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 4);
+ tt_int_op(hour,==, 23);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 59);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ format_time_interval(dbuf, sizeof(dbuf), 24*60*60 - 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 4);
+ tt_int_op(hour,==, 23);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 59);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* negative hours are reported as their absolute value */
+
+ /* ignore exact spelling of "hour(s)," etc., if present */
+ format_time_interval(dbuf, sizeof(dbuf), -2*60*60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &hour, label_h);
+ tt_int_op(r,==, 2);
+ tt_int_op(hour,==, 2);
+ tt_ci_char_op(label_h[0],==, 'h');
+
+ format_time_interval(dbuf, sizeof(dbuf), -75804);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 4);
+ tt_int_op(hour,==, 21);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 3);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* days: 1:00, 1:00:00:01, 1:00:01, 1:01 */
+ /* always ignore trailing seconds, if present */
+
+ /* ignore trailing "0 hours(s)" etc., if present */
+ format_time_interval(dbuf, sizeof(dbuf), 24*60*60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &day, label_d);
+ tt_int_op(r,==, 2);
+ tt_int_op(day,==, 1);
+ tt_ci_char_op(label_d[0],==, 'd');
+
+ format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 1);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_, &day, label_d);
+ tt_int_op(r,==, 2);
+ tt_int_op(day,==, 1);
+ tt_ci_char_op(label_d[0],==, 'd');
+
+ /* ignore exact spelling of "days(s)," etc. */
+ format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ if (r == -1) {
+ /* ignore 0 hours(s), if present */
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &day, label_d, &min, label_m);
+ }
+ tt_assert(r == 4 || r == 6);
+ tt_int_op(day,==, 1);
+ tt_ci_char_op(label_d[0],==, 'd');
+ if (r == 6) {
+ tt_int_op(hour,==, 0);
+ tt_ci_char_op(label_h[0],==, 'h');
+ }
+ tt_int_op(min,==, 1);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* ignore trailing "0 minutes(s)" etc., if present */
+ format_time_interval(dbuf, sizeof(dbuf), 24*60*60 + 60*60);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_,
+ &day, label_d, &hour, label_h);
+ tt_int_op(r,==, 4);
+ tt_int_op(day,==, 1);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 1);
+ tt_ci_char_op(label_h[0],==, 'h');
+
+ /* negative days are reported as their absolute value */
+
+ format_time_interval(dbuf, sizeof(dbuf), -21936184);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 253);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 21);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 23);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* periods > 1 year are reported in days (warn?) */
+
+ /* ignore exact spelling of "days(s)," etc., if present */
+ format_time_interval(dbuf, sizeof(dbuf), 758635154);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 8780);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 11);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 59);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+ /* negative periods > 1 year are reported in days (warn?) */
+
+ format_time_interval(dbuf, sizeof(dbuf), -1427014922);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 16516);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 9);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 2);
+ tt_ci_char_op(label_m[0],==, 'm');
+
+#if SIZEOF_LONG == 4 || SIZEOF_LONG == 8
+
+ /* We can try INT32_MIN/MAX */
+ /* Always ignore second(s) */
+
+ /* INT32_MAX */
+ format_time_interval(dbuf, sizeof(dbuf), 2147483647);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 24855);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 3);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 14);
+ tt_ci_char_op(label_m[0],==, 'm');
+ /* and 7 seconds - ignored */
+
+ /* INT32_MIN: check that we get the absolute value of interval,
+ * which doesn't actually fit in int32_t.
+ * We expect INT32_MAX or INT32_MAX + 1 with 64 bit longs */
+ format_time_interval(dbuf, sizeof(dbuf), -2147483647L - 1L);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 24855);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 3);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 14);
+ tt_ci_char_op(label_m[0],==, 'm');
+ /* and 7 or 8 seconds - ignored */
+
+#endif
+
+#if SIZEOF_LONG == 8
+
+ /* We can try INT64_MIN/MAX */
+ /* Always ignore second(s) */
+
+ /* INT64_MAX */
+ format_time_interval(dbuf, sizeof(dbuf), 9223372036854775807L);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 106751991167300L);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 15);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 30);
+ tt_ci_char_op(label_m[0],==, 'm');
+ /* and 7 seconds - ignored */
+
+ /* INT64_MIN: check that we get the absolute value of interval,
+ * which doesn't actually fit in int64_t.
+ * We expect INT64_MAX */
+ format_time_interval(dbuf, sizeof(dbuf),
+ -9223372036854775807L - 1L);
+ tt_int_op(strnlen(dbuf, DBUF_SIZE),<=, DBUF_SIZE - 1);
+ r = tor_sscanf(dbuf, TL_ " " TL_ " " TL_,
+ &day, label_d, &hour, label_h, &min, label_m);
+ tt_int_op(r,==, 6);
+ tt_int_op(day,==, 106751991167300L);
+ tt_ci_char_op(label_d[0],==, 'd');
+ tt_int_op(hour,==, 15);
+ tt_ci_char_op(label_h[0],==, 'h');
+ tt_int_op(min,==, 30);
+ tt_ci_char_op(label_m[0],==, 'm');
+ /* and 7 or 8 seconds - ignored */
+
+#endif
+
+ done:
+ ;
+}
+
+#undef tt_char_op
+#undef tt_ci_char_op
+#undef DBUF_SIZE
+#undef T_
+#undef LABEL_SIZE
+#undef L_
+#undef TL_
+
+static void
+test_util_path_is_relative(void *arg)
{
/* OS-independent tests */
- test_eq(1, path_is_relative(""));
- test_eq(1, path_is_relative("dir"));
- test_eq(1, path_is_relative("dir/"));
- test_eq(1, path_is_relative("./dir"));
- test_eq(1, path_is_relative("../dir"));
+ (void)arg;
+ tt_int_op(1,==, path_is_relative(""));
+ tt_int_op(1,==, path_is_relative("dir"));
+ tt_int_op(1,==, path_is_relative("dir/"));
+ tt_int_op(1,==, path_is_relative("./dir"));
+ tt_int_op(1,==, path_is_relative("../dir"));
- test_eq(0, path_is_relative("/"));
- test_eq(0, path_is_relative("/dir"));
- test_eq(0, path_is_relative("/dir/"));
+ tt_int_op(0,==, path_is_relative("/"));
+ tt_int_op(0,==, path_is_relative("/dir"));
+ tt_int_op(0,==, path_is_relative("/dir/"));
/* Windows */
#ifdef _WIN32
/* I don't have Windows so I can't test this, hence the "#ifdef
0". These are tests that look useful, so please try to get them
running and uncomment if it all works as it should */
- test_eq(1, path_is_relative("dir"));
- test_eq(1, path_is_relative("dir\\"));
- test_eq(1, path_is_relative("dir\\a:"));
- test_eq(1, path_is_relative("dir\\a:\\"));
- test_eq(1, path_is_relative("http:\\dir"));
-
- test_eq(0, path_is_relative("\\dir"));
- test_eq(0, path_is_relative("a:\\dir"));
- test_eq(0, path_is_relative("z:\\dir"));
+ tt_int_op(1,==, path_is_relative("dir"));
+ tt_int_op(1,==, path_is_relative("dir\\"));
+ tt_int_op(1,==, path_is_relative("dir\\a:"));
+ tt_int_op(1,==, path_is_relative("dir\\a:\\"));
+ tt_int_op(1,==, path_is_relative("http:\\dir"));
+
+ tt_int_op(0,==, path_is_relative("\\dir"));
+ tt_int_op(0,==, path_is_relative("a:\\dir"));
+ tt_int_op(0,==, path_is_relative("z:\\dir"));
#endif
done:
@@ -1922,25 +2769,26 @@ test_util_path_is_relative(void)
/** Run unittests for memory pool allocator */
static void
-test_util_mempool(void)
+test_util_mempool(void *arg)
{
mp_pool_t *pool = NULL;
smartlist_t *allocated = NULL;
int i;
+ (void)arg;
pool = mp_pool_new(1, 100);
- test_assert(pool);
- test_assert(pool->new_chunk_capacity >= 100);
- test_assert(pool->item_alloc_size >= sizeof(void*)+1);
+ tt_assert(pool);
+ tt_assert(pool->new_chunk_capacity >= 100);
+ tt_assert(pool->item_alloc_size >= sizeof(void*)+1);
mp_pool_destroy(pool);
pool = NULL;
pool = mp_pool_new(241, 2500);
- test_assert(pool);
- test_assert(pool->new_chunk_capacity >= 10);
- test_assert(pool->item_alloc_size >= sizeof(void*)+241);
- test_eq(pool->item_alloc_size & 0x03, 0);
- test_assert(pool->new_chunk_capacity < 60);
+ tt_assert(pool);
+ tt_assert(pool->new_chunk_capacity >= 10);
+ tt_assert(pool->item_alloc_size >= sizeof(void*)+241);
+ tt_int_op(pool->item_alloc_size & 0x03,==, 0);
+ tt_assert(pool->new_chunk_capacity < 60);
allocated = smartlist_new();
for (i = 0; i < 20000; ++i) {
@@ -1982,39 +2830,40 @@ test_util_mempool(void)
/** Run unittests for memory area allocator */
static void
-test_util_memarea(void)
+test_util_memarea(void *arg)
{
memarea_t *area = memarea_new();
char *p1, *p2, *p3, *p1_orig;
void *malloced_ptr = NULL;
int i;
- test_assert(area);
+ (void)arg;
+ tt_assert(area);
p1_orig = p1 = memarea_alloc(area,64);
p2 = memarea_alloc_zero(area,52);
p3 = memarea_alloc(area,11);
- test_assert(memarea_owns_ptr(area, p1));
- test_assert(memarea_owns_ptr(area, p2));
- test_assert(memarea_owns_ptr(area, p3));
+ tt_assert(memarea_owns_ptr(area, p1));
+ tt_assert(memarea_owns_ptr(area, p2));
+ tt_assert(memarea_owns_ptr(area, p3));
/* Make sure we left enough space. */
- test_assert(p1+64 <= p2);
- test_assert(p2+52 <= p3);
+ tt_assert(p1+64 <= p2);
+ tt_assert(p2+52 <= p3);
/* Make sure we aligned. */
- test_eq(((uintptr_t)p1) % sizeof(void*), 0);
- test_eq(((uintptr_t)p2) % sizeof(void*), 0);
- test_eq(((uintptr_t)p3) % sizeof(void*), 0);
- test_assert(!memarea_owns_ptr(area, p3+8192));
- test_assert(!memarea_owns_ptr(area, p3+30));
- test_assert(tor_mem_is_zero(p2, 52));
+ tt_int_op(((uintptr_t)p1) % sizeof(void*),==, 0);
+ tt_int_op(((uintptr_t)p2) % sizeof(void*),==, 0);
+ tt_int_op(((uintptr_t)p3) % sizeof(void*),==, 0);
+ tt_assert(!memarea_owns_ptr(area, p3+8192));
+ tt_assert(!memarea_owns_ptr(area, p3+30));
+ tt_assert(tor_mem_is_zero(p2, 52));
/* Make sure we don't overalign. */
p1 = memarea_alloc(area, 1);
p2 = memarea_alloc(area, 1);
- test_eq_ptr(p1+sizeof(void*), p2);
+ tt_ptr_op(p1+sizeof(void*),==, p2);
{
malloced_ptr = tor_malloc(64);
- test_assert(!memarea_owns_ptr(area, malloced_ptr));
+ tt_assert(!memarea_owns_ptr(area, malloced_ptr));
tor_free(malloced_ptr);
}
@@ -2023,18 +2872,18 @@ test_util_memarea(void)
malloced_ptr = tor_malloc(64);
crypto_rand((char*)malloced_ptr, 64);
p1 = memarea_memdup(area, malloced_ptr, 64);
- test_assert(p1 != malloced_ptr);
- test_memeq(p1, malloced_ptr, 64);
+ tt_assert(p1 != malloced_ptr);
+ tt_mem_op(p1,==, malloced_ptr, 64);
tor_free(malloced_ptr);
}
/* memarea_strdup. */
p1 = memarea_strdup(area,"");
p2 = memarea_strdup(area, "abcd");
- test_assert(p1);
- test_assert(p2);
- test_streq(p1, "");
- test_streq(p2, "abcd");
+ tt_assert(p1);
+ tt_assert(p2);
+ tt_str_op(p1,==, "");
+ tt_str_op(p2,==, "abcd");
/* memarea_strndup. */
{
@@ -2043,33 +2892,33 @@ test_util_memarea(void)
size_t len = strlen(s);
p1 = memarea_strndup(area, s, 1000);
p2 = memarea_strndup(area, s, 10);
- test_streq(p1, s);
- test_assert(p2 >= p1 + len + 1);
- test_memeq(s, p2, 10);
- test_eq(p2[10], '\0');
+ tt_str_op(p1,==, s);
+ tt_assert(p2 >= p1 + len + 1);
+ tt_mem_op(s,==, p2, 10);
+ tt_int_op(p2[10],==, '\0');
p3 = memarea_strndup(area, s, len);
- test_streq(p3, s);
+ tt_str_op(p3,==, s);
p3 = memarea_strndup(area, s, len-1);
- test_memeq(s, p3, len-1);
- test_eq(p3[len-1], '\0');
+ tt_mem_op(s,==, p3, len-1);
+ tt_int_op(p3[len-1],==, '\0');
}
memarea_clear(area);
p1 = memarea_alloc(area, 1);
- test_eq_ptr(p1, p1_orig);
+ tt_ptr_op(p1,==, p1_orig);
memarea_clear(area);
/* Check for running over an area's size. */
for (i = 0; i < 512; ++i) {
p1 = memarea_alloc(area, crypto_rand_int(5)+1);
- test_assert(memarea_owns_ptr(area, p1));
+ tt_assert(memarea_owns_ptr(area, p1));
}
memarea_assert_ok(area);
/* Make sure we can allocate a too-big object. */
p1 = memarea_alloc_zero(area, 9000);
p2 = memarea_alloc_zero(area, 16);
- test_assert(memarea_owns_ptr(area, p1));
- test_assert(memarea_owns_ptr(area, p2));
+ tt_assert(memarea_owns_ptr(area, p1));
+ tt_assert(memarea_owns_ptr(area, p2));
done:
memarea_drop_all(area);
@@ -2079,31 +2928,32 @@ test_util_memarea(void)
/** Run unit tests for utility functions to get file names relative to
* the data directory. */
static void
-test_util_datadir(void)
+test_util_datadir(void *arg)
{
char buf[1024];
char *f = NULL;
char *temp_dir = NULL;
+ (void)arg;
temp_dir = get_datadir_fname(NULL);
f = get_datadir_fname("state");
tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"state", temp_dir);
- test_streq(f, buf);
+ tt_str_op(f,==, buf);
tor_free(f);
f = get_datadir_fname2("cache", "thingy");
tor_snprintf(buf, sizeof(buf),
"%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy", temp_dir);
- test_streq(f, buf);
+ tt_str_op(f,==, buf);
tor_free(f);
f = get_datadir_fname2_suffix("cache", "thingy", ".foo");
tor_snprintf(buf, sizeof(buf),
"%s"PATH_SEPARATOR"cache"PATH_SEPARATOR"thingy.foo", temp_dir);
- test_streq(f, buf);
+ tt_str_op(f,==, buf);
tor_free(f);
f = get_datadir_fname_suffix("cache", ".foo");
tor_snprintf(buf, sizeof(buf), "%s"PATH_SEPARATOR"cache.foo",
temp_dir);
- test_streq(f, buf);
+ tt_str_op(f,==, buf);
done:
tor_free(f);
@@ -2111,13 +2961,14 @@ test_util_datadir(void)
}
static void
-test_util_strtok(void)
+test_util_strtok(void *arg)
{
char buf[128];
char buf2[128];
int i;
char *cp1, *cp2;
+ (void)arg;
for (i = 0; i < 3; i++) {
const char *pad1="", *pad2="";
switch (i) {
@@ -2134,8 +2985,8 @@ test_util_strtok(void)
}
tor_snprintf(buf, sizeof(buf), "%s", pad1);
tor_snprintf(buf2, sizeof(buf2), "%s", pad2);
- test_assert(NULL == tor_strtok_r_impl(buf, " ", &cp1));
- test_assert(NULL == tor_strtok_r_impl(buf2, ".!..;!", &cp2));
+ tt_assert(NULL == tor_strtok_r_impl(buf, " ", &cp1));
+ tt_assert(NULL == tor_strtok_r_impl(buf2, ".!..;!", &cp2));
tor_snprintf(buf, sizeof(buf),
"%sGraved on the dark in gestures of descent%s", pad1, pad1);
@@ -2143,43 +2994,43 @@ test_util_strtok(void)
"%sthey.seemed;;their!.own;most.perfect;monument%s",pad2,pad2);
/* -- "Year's End", Richard Wilbur */
- test_streq("Graved", tor_strtok_r_impl(buf, " ", &cp1));
- test_streq("they", tor_strtok_r_impl(buf2, ".!..;!", &cp2));
+ tt_str_op("Graved",==, tor_strtok_r_impl(buf, " ", &cp1));
+ tt_str_op("they",==, tor_strtok_r_impl(buf2, ".!..;!", &cp2));
#define S1() tor_strtok_r_impl(NULL, " ", &cp1)
#define S2() tor_strtok_r_impl(NULL, ".!..;!", &cp2)
- test_streq("on", S1());
- test_streq("the", S1());
- test_streq("dark", S1());
- test_streq("seemed", S2());
- test_streq("their", S2());
- test_streq("own", S2());
- test_streq("in", S1());
- test_streq("gestures", S1());
- test_streq("of", S1());
- test_streq("most", S2());
- test_streq("perfect", S2());
- test_streq("descent", S1());
- test_streq("monument", S2());
- test_eq_ptr(NULL, S1());
- test_eq_ptr(NULL, S2());
+ tt_str_op("on",==, S1());
+ tt_str_op("the",==, S1());
+ tt_str_op("dark",==, S1());
+ tt_str_op("seemed",==, S2());
+ tt_str_op("their",==, S2());
+ tt_str_op("own",==, S2());
+ tt_str_op("in",==, S1());
+ tt_str_op("gestures",==, S1());
+ tt_str_op("of",==, S1());
+ tt_str_op("most",==, S2());
+ tt_str_op("perfect",==, S2());
+ tt_str_op("descent",==, S1());
+ tt_str_op("monument",==, S2());
+ tt_ptr_op(NULL,==, S1());
+ tt_ptr_op(NULL,==, S2());
}
buf[0] = 0;
- test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1));
- test_eq_ptr(NULL, tor_strtok_r_impl(buf, "!", &cp1));
+ tt_ptr_op(NULL,==, tor_strtok_r_impl(buf, " ", &cp1));
+ tt_ptr_op(NULL,==, tor_strtok_r_impl(buf, "!", &cp1));
strlcpy(buf, "Howdy!", sizeof(buf));
- test_streq("Howdy", tor_strtok_r_impl(buf, "!", &cp1));
- test_eq_ptr(NULL, tor_strtok_r_impl(NULL, "!", &cp1));
+ tt_str_op("Howdy",==, tor_strtok_r_impl(buf, "!", &cp1));
+ tt_ptr_op(NULL,==, tor_strtok_r_impl(NULL, "!", &cp1));
strlcpy(buf, " ", sizeof(buf));
- test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1));
+ tt_ptr_op(NULL,==, tor_strtok_r_impl(buf, " ", &cp1));
strlcpy(buf, " ", sizeof(buf));
- test_eq_ptr(NULL, tor_strtok_r_impl(buf, " ", &cp1));
+ tt_ptr_op(NULL,==, tor_strtok_r_impl(buf, " ", &cp1));
strlcpy(buf, "something ", sizeof(buf));
- test_streq("something", tor_strtok_r_impl(buf, " ", &cp1));
- test_eq_ptr(NULL, tor_strtok_r_impl(NULL, ";", &cp1));
+ tt_str_op("something",==, tor_strtok_r_impl(buf, " ", &cp1));
+ tt_ptr_op(NULL,==, tor_strtok_r_impl(NULL, ";", &cp1));
done:
;
}
@@ -2199,23 +3050,24 @@ test_util_find_str_at_start_of_line(void *ptr)
(void)ptr;
- test_eq_ptr(long_string, find_str_at_start_of_line(long_string, ""));
- test_eq_ptr(NULL, find_str_at_start_of_line(short_string, "nonsense"));
- test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "nonsense"));
- test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "\n"));
- test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "how "));
- test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "kitty"));
- test_eq_ptr(long_string, find_str_at_start_of_line(long_string, "h"));
- test_eq_ptr(long_string, find_str_at_start_of_line(long_string, "how"));
- test_eq_ptr(line2, find_str_at_start_of_line(long_string, "he"));
- test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hell"));
- test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hello k"));
- test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hello kitty\n"));
- test_eq_ptr(line2, find_str_at_start_of_line(long_string, "hello kitty\nt"));
- test_eq_ptr(line3, find_str_at_start_of_line(long_string, "third"));
- test_eq_ptr(line3, find_str_at_start_of_line(long_string, "third line"));
- test_eq_ptr(NULL, find_str_at_start_of_line(long_string, "third line\n"));
- test_eq_ptr(short_line2, find_str_at_start_of_line(short_string,
+ tt_ptr_op(long_string,==, find_str_at_start_of_line(long_string, ""));
+ tt_ptr_op(NULL,==, find_str_at_start_of_line(short_string, "nonsense"));
+ tt_ptr_op(NULL,==, find_str_at_start_of_line(long_string, "nonsense"));
+ tt_ptr_op(NULL,==, find_str_at_start_of_line(long_string, "\n"));
+ tt_ptr_op(NULL,==, find_str_at_start_of_line(long_string, "how "));
+ tt_ptr_op(NULL,==, find_str_at_start_of_line(long_string, "kitty"));
+ tt_ptr_op(long_string,==, find_str_at_start_of_line(long_string, "h"));
+ tt_ptr_op(long_string,==, find_str_at_start_of_line(long_string, "how"));
+ tt_ptr_op(line2,==, find_str_at_start_of_line(long_string, "he"));
+ tt_ptr_op(line2,==, find_str_at_start_of_line(long_string, "hell"));
+ tt_ptr_op(line2,==, find_str_at_start_of_line(long_string, "hello k"));
+ tt_ptr_op(line2,==, find_str_at_start_of_line(long_string, "hello kitty\n"));
+ tt_ptr_op(line2,==,
+ find_str_at_start_of_line(long_string, "hello kitty\nt"));
+ tt_ptr_op(line3,==, find_str_at_start_of_line(long_string, "third"));
+ tt_ptr_op(line3,==, find_str_at_start_of_line(long_string, "third line"));
+ tt_ptr_op(NULL,==, find_str_at_start_of_line(long_string, "third line\n"));
+ tt_ptr_op(short_line2,==, find_str_at_start_of_line(short_string,
"second line\n"));
done:
;
@@ -2226,25 +3078,25 @@ test_util_string_is_C_identifier(void *ptr)
{
(void)ptr;
- test_eq(1, string_is_C_identifier("string_is_C_identifier"));
- test_eq(1, string_is_C_identifier("_string_is_C_identifier"));
- test_eq(1, string_is_C_identifier("_"));
- test_eq(1, string_is_C_identifier("i"));
- test_eq(1, string_is_C_identifier("_____"));
- test_eq(1, string_is_C_identifier("__00__"));
- test_eq(1, string_is_C_identifier("__init__"));
- test_eq(1, string_is_C_identifier("_0"));
- test_eq(1, string_is_C_identifier("_0string_is_C_identifier"));
- test_eq(1, string_is_C_identifier("_0"));
-
- test_eq(0, string_is_C_identifier("0_string_is_C_identifier"));
- test_eq(0, string_is_C_identifier("0"));
- test_eq(0, string_is_C_identifier(""));
- test_eq(0, string_is_C_identifier(";"));
- test_eq(0, string_is_C_identifier("i;"));
- test_eq(0, string_is_C_identifier("_;"));
- test_eq(0, string_is_C_identifier("í"));
- test_eq(0, string_is_C_identifier("ñ"));
+ tt_int_op(1,==, string_is_C_identifier("string_is_C_identifier"));
+ tt_int_op(1,==, string_is_C_identifier("_string_is_C_identifier"));
+ tt_int_op(1,==, string_is_C_identifier("_"));
+ tt_int_op(1,==, string_is_C_identifier("i"));
+ tt_int_op(1,==, string_is_C_identifier("_____"));
+ tt_int_op(1,==, string_is_C_identifier("__00__"));
+ tt_int_op(1,==, string_is_C_identifier("__init__"));
+ tt_int_op(1,==, string_is_C_identifier("_0"));
+ tt_int_op(1,==, string_is_C_identifier("_0string_is_C_identifier"));
+ tt_int_op(1,==, string_is_C_identifier("_0"));
+
+ tt_int_op(0,==, string_is_C_identifier("0_string_is_C_identifier"));
+ tt_int_op(0,==, string_is_C_identifier("0"));
+ tt_int_op(0,==, string_is_C_identifier(""));
+ tt_int_op(0,==, string_is_C_identifier(";"));
+ tt_int_op(0,==, string_is_C_identifier("i;"));
+ tt_int_op(0,==, string_is_C_identifier("_;"));
+ tt_int_op(0,==, string_is_C_identifier("í"));
+ tt_int_op(0,==, string_is_C_identifier("ñ"));
done:
;
@@ -2261,48 +3113,48 @@ test_util_asprintf(void *ptr)
/* simple string */
r = tor_asprintf(&cp, "simple string 100%% safe");
- test_assert(cp);
- test_streq("simple string 100% safe", cp);
- test_eq(strlen(cp), r);
+ tt_assert(cp);
+ tt_str_op("simple string 100% safe",==, cp);
+ tt_int_op(strlen(cp),==, r);
tor_free(cp);
/* empty string */
r = tor_asprintf(&cp, "%s", "");
- test_assert(cp);
- test_streq("", cp);
- test_eq(strlen(cp), r);
+ tt_assert(cp);
+ tt_str_op("",==, cp);
+ tt_int_op(strlen(cp),==, r);
tor_free(cp);
/* numbers (%i) */
r = tor_asprintf(&cp, "I like numbers-%2i, %i, etc.", -1, 2);
- test_assert(cp);
- test_streq("I like numbers--1, 2, etc.", cp);
- test_eq(strlen(cp), r);
+ tt_assert(cp);
+ tt_str_op("I like numbers--1, 2, etc.",==, cp);
+ tt_int_op(strlen(cp),==, r);
/* don't free cp; next test uses it. */
/* numbers (%d) */
r = tor_asprintf(&cp2, "First=%d, Second=%d", 101, 202);
- test_assert(cp2);
- test_eq(strlen(cp2), r);
- test_streq("First=101, Second=202", cp2);
- test_assert(cp != cp2);
+ tt_assert(cp2);
+ tt_int_op(strlen(cp2),==, r);
+ tt_str_op("First=101, Second=202",==, cp2);
+ tt_assert(cp != cp2);
tor_free(cp);
tor_free(cp2);
/* Glass-box test: a string exactly 128 characters long. */
r = tor_asprintf(&cp, "Lorem1: %sLorem2: %s", LOREMIPSUM, LOREMIPSUM);
- test_assert(cp);
- test_eq(128, r);
- test_assert(cp[128] == '\0');
- test_streq("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM, cp);
+ tt_assert(cp);
+ tt_int_op(128,==, r);
+ tt_int_op(cp[128], ==, '\0');
+ tt_str_op("Lorem1: "LOREMIPSUM"Lorem2: "LOREMIPSUM,==, cp);
tor_free(cp);
/* String longer than 128 characters */
r = tor_asprintf(&cp, "1: %s 2: %s 3: %s",
LOREMIPSUM, LOREMIPSUM, LOREMIPSUM);
- test_assert(cp);
- test_eq(strlen(cp), r);
- test_streq("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM, cp);
+ tt_assert(cp);
+ tt_int_op(strlen(cp),==, r);
+ tt_str_op("1: "LOREMIPSUM" 2: "LOREMIPSUM" 3: "LOREMIPSUM,==, cp);
done:
tor_free(cp);
@@ -2323,9 +3175,9 @@ test_util_listdir(void *ptr)
dir1 = tor_strdup(get_fname("some-directory"));
dirname = tor_strdup(get_fname(NULL));
- test_eq(0, write_str_to_file(fname1, "X\n", 0));
- test_eq(0, write_str_to_file(fname2, "Y\n", 0));
- test_eq(0, write_str_to_file(fname3, "Z\n", 0));
+ tt_int_op(0,==, write_str_to_file(fname1, "X\n", 0));
+ tt_int_op(0,==, write_str_to_file(fname2, "Y\n", 0));
+ tt_int_op(0,==, write_str_to_file(fname3, "Z\n", 0));
#ifdef _WIN32
r = mkdir(dir1);
#else
@@ -2338,15 +3190,15 @@ test_util_listdir(void *ptr)
}
dir_contents = tor_listdir(dirname);
- test_assert(dir_contents);
+ tt_assert(dir_contents);
/* make sure that each filename is listed. */
- test_assert(smartlist_contains_string_case(dir_contents, "hopscotch"));
- test_assert(smartlist_contains_string_case(dir_contents, "mumblety-peg"));
- test_assert(smartlist_contains_string_case(dir_contents, ".hidden-file"));
- test_assert(smartlist_contains_string_case(dir_contents, "some-directory"));
+ tt_assert(smartlist_contains_string_case(dir_contents, "hopscotch"));
+ tt_assert(smartlist_contains_string_case(dir_contents, "mumblety-peg"));
+ tt_assert(smartlist_contains_string_case(dir_contents, ".hidden-file"));
+ tt_assert(smartlist_contains_string_case(dir_contents, "some-directory"));
- test_assert(!smartlist_contains_string(dir_contents, "."));
- test_assert(!smartlist_contains_string(dir_contents, ".."));
+ tt_assert(!smartlist_contains_string(dir_contents, "."));
+ tt_assert(!smartlist_contains_string(dir_contents, ".."));
done:
tor_free(fname1);
@@ -2486,30 +3338,53 @@ test_util_exit_status(void *ptr)
(void)ptr;
clear_hex_errno(hex_errno);
+ tt_str_op("",==, hex_errno);
+
+ clear_hex_errno(hex_errno);
n = format_helper_exit_status(0, 0, hex_errno);
- test_streq("0/0\n", hex_errno);
- test_eq(n, strlen(hex_errno));
+ tt_str_op("0/0\n",==, hex_errno);
+ tt_int_op(n,==, strlen(hex_errno));
+
+#if SIZEOF_INT == 4
clear_hex_errno(hex_errno);
n = format_helper_exit_status(0, 0x7FFFFFFF, hex_errno);
- test_streq("0/7FFFFFFF\n", hex_errno);
- test_eq(n, strlen(hex_errno));
+ tt_str_op("0/7FFFFFFF\n",==, hex_errno);
+ tt_int_op(n,==, strlen(hex_errno));
clear_hex_errno(hex_errno);
n = format_helper_exit_status(0xFF, -0x80000000, hex_errno);
- test_streq("FF/-80000000\n", hex_errno);
- test_eq(n, strlen(hex_errno));
- test_eq(n, HEX_ERRNO_SIZE);
+ tt_str_op("FF/-80000000\n",==, hex_errno);
+ tt_int_op(n,==, strlen(hex_errno));
+ tt_int_op(n,==, HEX_ERRNO_SIZE);
+
+#elif SIZEOF_INT == 8
+
+ clear_hex_errno(hex_errno);
+ n = format_helper_exit_status(0, 0x7FFFFFFFFFFFFFFF, hex_errno);
+ tt_str_op("0/7FFFFFFFFFFFFFFF\n",==, hex_errno);
+ tt_int_op(n,==, strlen(hex_errno));
+
+ clear_hex_errno(hex_errno);
+ n = format_helper_exit_status(0xFF, -0x8000000000000000, hex_errno);
+ tt_str_op("FF/-8000000000000000\n",==, hex_errno);
+ tt_int_op(n,==, strlen(hex_errno));
+ tt_int_op(n,==, HEX_ERRNO_SIZE);
+
+#endif
clear_hex_errno(hex_errno);
n = format_helper_exit_status(0x7F, 0, hex_errno);
- test_streq("7F/0\n", hex_errno);
- test_eq(n, strlen(hex_errno));
+ tt_str_op("7F/0\n",==, hex_errno);
+ tt_int_op(n,==, strlen(hex_errno));
clear_hex_errno(hex_errno);
n = format_helper_exit_status(0x08, -0x242, hex_errno);
- test_streq("8/-242\n", hex_errno);
- test_eq(n, strlen(hex_errno));
+ tt_str_op("8/-242\n",==, hex_errno);
+ tt_int_op(n,==, strlen(hex_errno));
+
+ clear_hex_errno(hex_errno);
+ tt_str_op("",==, hex_errno);
done:
;
@@ -2637,6 +3512,30 @@ test_util_fgets_eagain(void *ptr)
#define EOL "\n"
#endif
+#ifdef _WIN32
+/* I've assumed Windows doesn't have the gap between fork and exec
+ * that causes the race condition on unix-like platforms */
+#define MATCH_PROCESS_STATUS(s1,s2) ((s1) == (s2))
+
+#else
+/* work around a race condition of the timing of SIGCHLD handler updates
+ * to the process_handle's fields, and checks of those fields
+ *
+ * TODO: Once we can signal failure to exec, change PROCESS_STATUS_RUNNING to
+ * PROCESS_STATUS_ERROR (and similarly with *_OR_NOTRUNNING) */
+#define PROCESS_STATUS_RUNNING_OR_NOTRUNNING (PROCESS_STATUS_RUNNING+1)
+#define IS_RUNNING_OR_NOTRUNNING(s) \
+ ((s) == PROCESS_STATUS_RUNNING || (s) == PROCESS_STATUS_NOTRUNNING)
+/* well, this is ugly */
+#define MATCH_PROCESS_STATUS(s1,s2) \
+ ( (s1) == (s2) \
+ ||((s1) == PROCESS_STATUS_RUNNING_OR_NOTRUNNING \
+ && IS_RUNNING_OR_NOTRUNNING(s2)) \
+ ||((s2) == PROCESS_STATUS_RUNNING_OR_NOTRUNNING \
+ && IS_RUNNING_OR_NOTRUNNING(s1)))
+
+#endif // _WIN32
+
/** Helper function for testing tor_spawn_background */
static void
run_util_spawn_background(const char *argv[], const char *expected_out,
@@ -2658,26 +3557,47 @@ run_util_spawn_background(const char *argv[], const char *expected_out,
notify_pending_waitpid_callbacks();
- test_eq(expected_status, status);
+ /* the race condition doesn't affect status,
+ * because status isn't updated by the SIGCHLD handler,
+ * but we still need to handle PROCESS_STATUS_RUNNING_OR_NOTRUNNING */
+ tt_assert(MATCH_PROCESS_STATUS(expected_status, status));
if (status == PROCESS_STATUS_ERROR) {
tt_ptr_op(process_handle, ==, NULL);
return;
}
- test_assert(process_handle != NULL);
- test_eq(expected_status, process_handle->status);
+ tt_assert(process_handle != NULL);
+
+ /* When a spawned process forks, fails, then exits very quickly,
+ * (this typically occurs when exec fails)
+ * there is a race condition between the SIGCHLD handler
+ * updating the process_handle's fields, and this test
+ * checking the process status in those fields.
+ * The SIGCHLD update can occur before or after the code below executes.
+ * This causes intermittent failures in spawn_background_fail(),
+ * typically when the machine is under load.
+ * We use PROCESS_STATUS_RUNNING_OR_NOTRUNNING to avoid this issue. */
+
+ /* the race condition affects the change in
+ * process_handle->status from RUNNING to NOTRUNNING */
+ tt_assert(MATCH_PROCESS_STATUS(expected_status, process_handle->status));
#ifndef _WIN32
notify_pending_waitpid_callbacks();
- tt_ptr_op(process_handle->waitpid_cb, !=, NULL);
+ /* the race condition affects the change in
+ * process_handle->waitpid_cb to NULL,
+ * so we skip the check if expected_status is ambiguous,
+ * that is, PROCESS_STATUS_RUNNING_OR_NOTRUNNING */
+ tt_assert(process_handle->waitpid_cb != NULL
+ || expected_status == PROCESS_STATUS_RUNNING_OR_NOTRUNNING);
#endif
#ifdef _WIN32
- test_assert(process_handle->stdout_pipe != INVALID_HANDLE_VALUE);
- test_assert(process_handle->stderr_pipe != INVALID_HANDLE_VALUE);
+ tt_assert(process_handle->stdout_pipe != INVALID_HANDLE_VALUE);
+ tt_assert(process_handle->stderr_pipe != INVALID_HANDLE_VALUE);
#else
- test_assert(process_handle->stdout_pipe >= 0);
- test_assert(process_handle->stderr_pipe >= 0);
+ tt_assert(process_handle->stdout_pipe >= 0);
+ tt_assert(process_handle->stderr_pipe >= 0);
#endif
/* Check stdout */
@@ -2685,15 +3605,15 @@ run_util_spawn_background(const char *argv[], const char *expected_out,
sizeof(stdout_buf) - 1);
tt_assert(pos >= 0);
stdout_buf[pos] = '\0';
- test_eq(strlen(expected_out), pos);
- test_streq(expected_out, stdout_buf);
+ tt_int_op(strlen(expected_out),==, pos);
+ tt_str_op(expected_out,==, stdout_buf);
notify_pending_waitpid_callbacks();
/* Check it terminated correctly */
retval = tor_get_exit_code(process_handle, 1, &exit_code);
- test_eq(PROCESS_EXIT_EXITED, retval);
- test_eq(expected_exit, exit_code);
+ tt_int_op(PROCESS_EXIT_EXITED,==, retval);
+ tt_int_op(expected_exit,==, exit_code);
// TODO: Make test-child exit with something other than 0
#ifndef _WIN32
@@ -2704,10 +3624,10 @@ run_util_spawn_background(const char *argv[], const char *expected_out,
/* Check stderr */
pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
sizeof(stderr_buf) - 1);
- test_assert(pos >= 0);
+ tt_assert(pos >= 0);
stderr_buf[pos] = '\0';
- test_streq(expected_err, stderr_buf);
- test_eq(strlen(expected_err), pos);
+ tt_str_op(expected_err,==, stderr_buf);
+ tt_int_op(strlen(expected_err),==, pos);
notify_pending_waitpid_callbacks();
@@ -2742,10 +3662,13 @@ test_util_spawn_background_fail(void *ptr)
const int expected_status = PROCESS_STATUS_ERROR;
#else
/* TODO: Once we can signal failure to exec, set this to be
- * PROCESS_STATUS_ERROR */
- const int expected_status = PROCESS_STATUS_RUNNING;
+ * PROCESS_STATUS_RUNNING_OR_ERROR */
+ const int expected_status = PROCESS_STATUS_RUNNING_OR_NOTRUNNING;
#endif
+ memset(expected_out, 0xf0, sizeof(expected_out));
+ memset(code, 0xf0, sizeof(code));
+
(void)ptr;
tor_snprintf(code, sizeof(code), "%x/%x",
@@ -2793,9 +3716,9 @@ test_util_spawn_background_partial_read_impl(int exit_early)
#else
status = tor_spawn_background(argv[0], argv, NULL, &process_handle);
#endif
- test_eq(expected_status, status);
- test_assert(process_handle);
- test_eq(expected_status, process_handle->status);
+ tt_int_op(expected_status,==, status);
+ tt_assert(process_handle);
+ tt_int_op(expected_status,==, process_handle->status);
/* Check stdout */
for (expected_out_ctr = 0; expected_out[expected_out_ctr] != NULL;) {
@@ -2804,7 +3727,7 @@ test_util_spawn_background_partial_read_impl(int exit_early)
sizeof(stdout_buf) - 1, NULL);
#else
/* Check that we didn't read the end of file last time */
- test_assert(!eof);
+ tt_assert(!eof);
pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf,
sizeof(stdout_buf) - 1, NULL, &eof);
#endif
@@ -2814,10 +3737,10 @@ test_util_spawn_background_partial_read_impl(int exit_early)
if (0 == pos)
continue;
- test_assert(pos > 0);
+ tt_assert(pos > 0);
stdout_buf[pos] = '\0';
- test_streq(expected_out[expected_out_ctr], stdout_buf);
- test_eq(strlen(expected_out[expected_out_ctr]), pos);
+ tt_str_op(expected_out[expected_out_ctr],==, stdout_buf);
+ tt_int_op(strlen(expected_out[expected_out_ctr]),==, pos);
expected_out_ctr++;
}
@@ -2832,33 +3755,33 @@ test_util_spawn_background_partial_read_impl(int exit_early)
pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf,
sizeof(stdout_buf) - 1,
process_handle);
- test_eq(0, pos);
+ tt_int_op(0,==, pos);
#else
if (!eof) {
/* We should have got all the data, but maybe not the EOF flag */
pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf,
sizeof(stdout_buf) - 1,
process_handle, &eof);
- test_eq(0, pos);
- test_assert(eof);
+ tt_int_op(0,==, pos);
+ tt_assert(eof);
}
/* Otherwise, we got the EOF on the last read */
#endif
/* Check it terminated correctly */
retval = tor_get_exit_code(process_handle, 1, &exit_code);
- test_eq(PROCESS_EXIT_EXITED, retval);
- test_eq(expected_exit, exit_code);
+ tt_int_op(PROCESS_EXIT_EXITED,==, retval);
+ tt_int_op(expected_exit,==, exit_code);
// TODO: Make test-child exit with something other than 0
/* Check stderr */
pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
sizeof(stderr_buf) - 1);
- test_assert(pos >= 0);
+ tt_assert(pos >= 0);
stderr_buf[pos] = '\0';
- test_streq(expected_err, stderr_buf);
- test_eq(strlen(expected_err), pos);
+ tt_str_op(expected_err,==, stderr_buf);
+ tt_int_op(strlen(expected_err),==, pos);
done:
tor_process_handle_destroy(process_handle, 1);
@@ -2933,6 +3856,13 @@ test_util_spawn_background_waitpid_notify(void *arg)
#undef TEST_CHILD
#undef EOL
+#undef MATCH_PROCESS_STATUS
+
+#ifndef _WIN32
+#undef PROCESS_STATUS_RUNNING_OR_NOTRUNNING
+#undef IS_RUNNING_OR_NOTRUNNING
+#endif
+
/**
* Test for format_hex_number_sigsafe()
*/
@@ -2963,15 +3893,15 @@ test_util_format_hex_number(void *ptr)
for (i = 0; test_data[i].str != NULL; ++i) {
len = format_hex_number_sigsafe(test_data[i].x, buf, sizeof(buf));
- test_neq(len, 0);
- test_eq(len, strlen(buf));
- test_streq(buf, test_data[i].str);
+ tt_int_op(len,!=, 0);
+ tt_int_op(len,==, strlen(buf));
+ tt_str_op(buf,==, test_data[i].str);
}
- test_eq(4, format_hex_number_sigsafe(0xffff, buf, 5));
- test_streq(buf, "FFFF");
- test_eq(0, format_hex_number_sigsafe(0xffff, buf, 4));
- test_eq(0, format_hex_number_sigsafe(0, buf, 1));
+ tt_int_op(4,==, format_hex_number_sigsafe(0xffff, buf, 5));
+ tt_str_op(buf,==, "FFFF");
+ tt_int_op(0,==, format_hex_number_sigsafe(0xffff, buf, 4));
+ tt_int_op(0,==, format_hex_number_sigsafe(0, buf, 1));
done:
return;
@@ -3007,21 +3937,21 @@ test_util_format_dec_number(void *ptr)
for (i = 0; test_data[i].str != NULL; ++i) {
len = format_dec_number_sigsafe(test_data[i].x, buf, sizeof(buf));
- test_neq(len, 0);
- test_eq(len, strlen(buf));
- test_streq(buf, test_data[i].str);
+ tt_int_op(len,!=, 0);
+ tt_int_op(len,==, strlen(buf));
+ tt_str_op(buf,==, test_data[i].str);
len = format_dec_number_sigsafe(test_data[i].x, buf,
(int)(strlen(test_data[i].str) + 1));
- test_eq(len, strlen(buf));
- test_streq(buf, test_data[i].str);
+ tt_int_op(len,==, strlen(buf));
+ tt_str_op(buf,==, test_data[i].str);
}
- test_eq(4, format_dec_number_sigsafe(7331, buf, 5));
- test_streq(buf, "7331");
- test_eq(0, format_dec_number_sigsafe(7331, buf, 4));
- test_eq(1, format_dec_number_sigsafe(0, buf, 2));
- test_eq(0, format_dec_number_sigsafe(0, buf, 1));
+ tt_int_op(4,==, format_dec_number_sigsafe(7331, buf, 5));
+ tt_str_op(buf,==, "7331");
+ tt_int_op(0,==, format_dec_number_sigsafe(7331, buf, 4));
+ tt_int_op(1,==, format_dec_number_sigsafe(0, buf, 2));
+ tt_int_op(0,==, format_dec_number_sigsafe(0, buf, 1));
done:
return;
@@ -3070,7 +4000,7 @@ test_util_join_win_cmdline(void *ptr)
for (i=0; cmdlines[i]!=NULL; i++) {
log_info(LD_GENERAL, "Joining argvs[%d], expecting <%s>", i, cmdlines[i]);
joined_argv = tor_join_win_cmdline(argvs[i]);
- test_streq(cmdlines[i], joined_argv);
+ tt_str_op(cmdlines[i],==, joined_argv);
tor_free(joined_argv);
}
@@ -3125,17 +4055,17 @@ test_util_split_lines(void *ptr)
i, tests[i].orig_length);
SMARTLIST_FOREACH_BEGIN(sl, const char *, line) {
/* Check we have not got too many lines */
- test_assert(j < MAX_SPLIT_LINE_COUNT);
+ tt_int_op(MAX_SPLIT_LINE_COUNT, >, j);
/* Check that there actually should be a line here */
- test_assert(tests[i].split_line[j] != NULL);
+ tt_assert(tests[i].split_line[j] != NULL);
log_info(LD_GENERAL, "Line %d of test %d, should be <%s>",
j, i, tests[i].split_line[j]);
/* Check that the line is as expected */
- test_streq(line, tests[i].split_line[j]);
+ tt_str_op(line,==, tests[i].split_line[j]);
j++;
} SMARTLIST_FOREACH_END(line);
/* Check that we didn't miss some lines */
- test_eq_ptr(NULL, tests[i].split_line[j]);
+ tt_ptr_op(NULL,==, tests[i].split_line[j]);
tor_free(orig_line);
smartlist_free(sl);
sl = NULL;
@@ -3147,7 +4077,7 @@ test_util_split_lines(void *ptr)
}
static void
-test_util_di_ops(void)
+test_util_di_ops(void *arg)
{
#define LT -1
#define GT 1
@@ -3167,10 +4097,11 @@ test_util_di_ops(void)
int i;
+ (void)arg;
for (i = 0; examples[i].a; ++i) {
size_t len = strlen(examples[i].a);
int eq1, eq2, neq1, neq2, cmp1, cmp2;
- test_eq(len, strlen(examples[i].b));
+ tt_int_op(len,==, strlen(examples[i].b));
/* We do all of the operations, with operands in both orders. */
eq1 = tor_memeq(examples[i].a, examples[i].b, len);
eq2 = tor_memeq(examples[i].b, examples[i].a, len);
@@ -3181,18 +4112,37 @@ test_util_di_ops(void)
/* Check for correctness of cmp1 */
if (cmp1 < 0 && examples[i].want_sign != LT)
- test_fail();
+ TT_DIE(("Assertion failed."));
else if (cmp1 > 0 && examples[i].want_sign != GT)
- test_fail();
+ TT_DIE(("Assertion failed."));
else if (cmp1 == 0 && examples[i].want_sign != EQ)
- test_fail();
+ TT_DIE(("Assertion failed."));
/* Check for consistency of everything else with cmp1 */
- test_eq(eq1, eq2);
- test_eq(neq1, neq2);
- test_eq(cmp1, -cmp2);
- test_eq(eq1, cmp1 == 0);
- test_eq(neq1, !eq1);
+ tt_int_op(eq1,==, eq2);
+ tt_int_op(neq1,==, neq2);
+ tt_int_op(cmp1,==, -cmp2);
+ tt_int_op(eq1,==, cmp1 == 0);
+ tt_int_op(neq1,==, !eq1);
+ }
+
+ {
+ uint8_t zz = 0;
+ uint8_t ii = 0;
+ int z;
+
+ /* exhaustively test tor_memeq and tor_memcmp
+ * against each possible single-byte numeric difference
+ * some arithmetic bugs only appear with certain bit patterns */
+ for (z = 0; z < 256; z++) {
+ for (i = 0; i < 256; i++) {
+ ii = (uint8_t)i;
+ zz = (uint8_t)z;
+ tt_int_op(tor_memeq(&zz, &ii, 1),==, zz == ii);
+ tt_int_op(tor_memcmp(&zz, &ii, 1) > 0 ? GT : EQ,==, zz > ii ? GT : EQ);
+ tt_int_op(tor_memcmp(&ii, &zz, 1) < 0 ? LT : EQ,==, ii < zz ? LT : EQ);
+ }
+ }
}
tt_int_op(1, ==, safe_mem_is_zero("", 0));
@@ -3216,12 +4166,12 @@ static void
test_util_n_bits_set(void *ptr)
{
(void)ptr;
- test_eq(0, n_bits_set_u8(0));
- test_eq(1, n_bits_set_u8(1));
- test_eq(3, n_bits_set_u8(7));
- test_eq(1, n_bits_set_u8(8));
- test_eq(2, n_bits_set_u8(129));
- test_eq(8, n_bits_set_u8(255));
+ tt_int_op(0,==, n_bits_set_u8(0));
+ tt_int_op(1,==, n_bits_set_u8(1));
+ tt_int_op(3,==, n_bits_set_u8(7));
+ tt_int_op(1,==, n_bits_set_u8(8));
+ tt_int_op(2,==, n_bits_set_u8(129));
+ tt_int_op(8,==, n_bits_set_u8(255));
done:
;
}
@@ -3242,78 +4192,78 @@ test_util_eat_whitespace(void *ptr)
strlcpy(str, "fuubaar", sizeof(str));
for (i = 0; i < sizeof(ws); ++i) {
str[0] = ws[i];
- test_eq_ptr(str + 1, eat_whitespace(str));
- test_eq_ptr(str + 1, eat_whitespace_eos(str, str + strlen(str)));
- test_eq_ptr(str + 1, eat_whitespace_no_nl(str));
- test_eq_ptr(str + 1, eat_whitespace_eos_no_nl(str, str + strlen(str)));
+ tt_ptr_op(str + 1,==, eat_whitespace(str));
+ tt_ptr_op(str + 1,==, eat_whitespace_eos(str, str + strlen(str)));
+ tt_ptr_op(str + 1,==, eat_whitespace_no_nl(str));
+ tt_ptr_op(str + 1,==, eat_whitespace_eos_no_nl(str, str + strlen(str)));
}
str[0] = '\n';
- test_eq_ptr(str + 1, eat_whitespace(str));
- test_eq_ptr(str + 1, eat_whitespace_eos(str, str + strlen(str)));
- test_eq_ptr(str, eat_whitespace_no_nl(str));
- test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str + strlen(str)));
+ tt_ptr_op(str + 1,==, eat_whitespace(str));
+ tt_ptr_op(str + 1,==, eat_whitespace_eos(str, str + strlen(str)));
+ tt_ptr_op(str,==, eat_whitespace_no_nl(str));
+ tt_ptr_op(str,==, eat_whitespace_eos_no_nl(str, str + strlen(str)));
/* Empty string */
strlcpy(str, "", sizeof(str));
- test_eq_ptr(str, eat_whitespace(str));
- test_eq_ptr(str, eat_whitespace_eos(str, str));
- test_eq_ptr(str, eat_whitespace_no_nl(str));
- test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str));
+ tt_ptr_op(str,==, eat_whitespace(str));
+ tt_ptr_op(str,==, eat_whitespace_eos(str, str));
+ tt_ptr_op(str,==, eat_whitespace_no_nl(str));
+ tt_ptr_op(str,==, eat_whitespace_eos_no_nl(str, str));
/* Only ws */
strlcpy(str, " \t\r\n", sizeof(str));
- test_eq_ptr(str + strlen(str), eat_whitespace(str));
- test_eq_ptr(str + strlen(str), eat_whitespace_eos(str, str + strlen(str)));
- test_eq_ptr(str + strlen(str) - 1,
+ tt_ptr_op(str + strlen(str),==, eat_whitespace(str));
+ tt_ptr_op(str + strlen(str),==, eat_whitespace_eos(str, str + strlen(str)));
+ tt_ptr_op(str + strlen(str) - 1,==,
eat_whitespace_no_nl(str));
- test_eq_ptr(str + strlen(str) - 1,
+ tt_ptr_op(str + strlen(str) - 1,==,
eat_whitespace_eos_no_nl(str, str + strlen(str)));
strlcpy(str, " \t\r ", sizeof(str));
- test_eq_ptr(str + strlen(str), eat_whitespace(str));
- test_eq_ptr(str + strlen(str),
+ tt_ptr_op(str + strlen(str),==, eat_whitespace(str));
+ tt_ptr_op(str + strlen(str),==,
eat_whitespace_eos(str, str + strlen(str)));
- test_eq_ptr(str + strlen(str), eat_whitespace_no_nl(str));
- test_eq_ptr(str + strlen(str),
+ tt_ptr_op(str + strlen(str),==, eat_whitespace_no_nl(str));
+ tt_ptr_op(str + strlen(str),==,
eat_whitespace_eos_no_nl(str, str + strlen(str)));
/* Multiple ws */
strlcpy(str, "fuubaar", sizeof(str));
for (i = 0; i < sizeof(ws); ++i)
str[i] = ws[i];
- test_eq_ptr(str + sizeof(ws), eat_whitespace(str));
- test_eq_ptr(str + sizeof(ws), eat_whitespace_eos(str, str + strlen(str)));
- test_eq_ptr(str + sizeof(ws), eat_whitespace_no_nl(str));
- test_eq_ptr(str + sizeof(ws),
+ tt_ptr_op(str + sizeof(ws),==, eat_whitespace(str));
+ tt_ptr_op(str + sizeof(ws),==, eat_whitespace_eos(str, str + strlen(str)));
+ tt_ptr_op(str + sizeof(ws),==, eat_whitespace_no_nl(str));
+ tt_ptr_op(str + sizeof(ws),==,
eat_whitespace_eos_no_nl(str, str + strlen(str)));
/* Eat comment */
strlcpy(str, "# Comment \n No Comment", sizeof(str));
- test_streq("No Comment", eat_whitespace(str));
- test_streq("No Comment", eat_whitespace_eos(str, str + strlen(str)));
- test_eq_ptr(str, eat_whitespace_no_nl(str));
- test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str + strlen(str)));
+ tt_str_op("No Comment",==, eat_whitespace(str));
+ tt_str_op("No Comment",==, eat_whitespace_eos(str, str + strlen(str)));
+ tt_ptr_op(str,==, eat_whitespace_no_nl(str));
+ tt_ptr_op(str,==, eat_whitespace_eos_no_nl(str, str + strlen(str)));
/* Eat comment & ws mix */
strlcpy(str, " # \t Comment \n\t\nNo Comment", sizeof(str));
- test_streq("No Comment", eat_whitespace(str));
- test_streq("No Comment", eat_whitespace_eos(str, str + strlen(str)));
- test_eq_ptr(str + 1, eat_whitespace_no_nl(str));
- test_eq_ptr(str + 1, eat_whitespace_eos_no_nl(str, str + strlen(str)));
+ tt_str_op("No Comment",==, eat_whitespace(str));
+ tt_str_op("No Comment",==, eat_whitespace_eos(str, str + strlen(str)));
+ tt_ptr_op(str + 1,==, eat_whitespace_no_nl(str));
+ tt_ptr_op(str + 1,==, eat_whitespace_eos_no_nl(str, str + strlen(str)));
/* Eat entire comment */
strlcpy(str, "#Comment", sizeof(str));
- test_eq_ptr(str + strlen(str), eat_whitespace(str));
- test_eq_ptr(str + strlen(str), eat_whitespace_eos(str, str + strlen(str)));
- test_eq_ptr(str, eat_whitespace_no_nl(str));
- test_eq_ptr(str, eat_whitespace_eos_no_nl(str, str + strlen(str)));
+ tt_ptr_op(str + strlen(str),==, eat_whitespace(str));
+ tt_ptr_op(str + strlen(str),==, eat_whitespace_eos(str, str + strlen(str)));
+ tt_ptr_op(str,==, eat_whitespace_no_nl(str));
+ tt_ptr_op(str,==, eat_whitespace_eos_no_nl(str, str + strlen(str)));
/* Blank line, then comment */
strlcpy(str, " \t\n # Comment", sizeof(str));
- test_eq_ptr(str + strlen(str), eat_whitespace(str));
- test_eq_ptr(str + strlen(str), eat_whitespace_eos(str, str + strlen(str)));
- test_eq_ptr(str + 2, eat_whitespace_no_nl(str));
- test_eq_ptr(str + 2, eat_whitespace_eos_no_nl(str, str + strlen(str)));
+ tt_ptr_op(str + strlen(str),==, eat_whitespace(str));
+ tt_ptr_op(str + strlen(str),==, eat_whitespace_eos(str, str + strlen(str)));
+ tt_ptr_op(str + 2,==, eat_whitespace_no_nl(str));
+ tt_ptr_op(str + 2,==, eat_whitespace_eos_no_nl(str, str + strlen(str)));
done:
;
@@ -3641,12 +4591,12 @@ test_util_round_to_next_multiple_of(void *arg)
{
(void)arg;
- test_assert(round_uint64_to_next_multiple_of(0,1) == 0);
- test_assert(round_uint64_to_next_multiple_of(0,7) == 0);
+ tt_assert(round_uint64_to_next_multiple_of(0,1) == 0);
+ tt_assert(round_uint64_to_next_multiple_of(0,7) == 0);
- test_assert(round_uint64_to_next_multiple_of(99,1) == 99);
- test_assert(round_uint64_to_next_multiple_of(99,7) == 105);
- test_assert(round_uint64_to_next_multiple_of(99,9) == 99);
+ tt_assert(round_uint64_to_next_multiple_of(99,1) == 99);
+ tt_assert(round_uint64_to_next_multiple_of(99,7) == 105);
+ tt_assert(round_uint64_to_next_multiple_of(99,9) == 99);
done:
;
@@ -3673,7 +4623,7 @@ test_util_strclear(void *arg)
}
#define UTIL_LEGACY(name) \
- { #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name }
+ { #name, test_util_ ## name , 0, NULL, NULL }
#define UTIL_TEST(name, flags) \
{ #name, test_util_ ## name, flags, NULL, NULL }
@@ -3858,6 +4808,7 @@ struct testcase_t util_tests[] = {
UTIL_LEGACY(mmap),
UTIL_LEGACY(threads),
UTIL_LEGACY(sscanf),
+ UTIL_LEGACY(format_time_interval),
UTIL_LEGACY(path_is_relative),
UTIL_LEGACY(strtok),
UTIL_LEGACY(di_ops),
diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c
index 1b1e6745cb..74af511acb 100644
--- a/src/tools/tor-resolve.c
+++ b/src/tools/tor-resolve.c
@@ -8,6 +8,7 @@
#include "../common/util.h"
#include "address.h"
#include "../common/torlog.h"
+#include "sandbox.h"
#include <stdio.h>
#include <stdlib.h>
@@ -344,6 +345,7 @@ main(int argc, char **argv)
log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t));
init_logging(1);
+ sandbox_disable_getaddrinfo_cache();
arg = &argv[1];
n_args = argc-1;
diff --git a/src/trunnel/include.am b/src/trunnel/include.am
new file mode 100644
index 0000000000..c7ac1679d0
--- /dev/null
+++ b/src/trunnel/include.am
@@ -0,0 +1,29 @@
+
+noinst_LIBRARIES += \
+ src/trunnel/libor-trunnel.a
+
+if UNITTESTS_ENABLED
+noinst_LIBRARIES += \
+ src/trunnel/libor-trunnel-testing.a
+endif
+
+AM_CPPFLAGS += -I$(srcdir)/src/ext/trunnel -I$(srcdir)/src/trunnel
+
+TRUNNELSOURCES = \
+ src/ext/trunnel/trunnel.c \
+ src/trunnel/pwbox.c
+
+TRUNNELHEADERS = \
+ src/ext/trunnel/trunnel.h \
+ src/ext/trunnel/trunnel-impl.h \
+ src/trunnel/trunnel-local.h \
+ src/trunnel/pwbox.h
+
+src_trunnel_libor_trunnel_a_SOURCES = $(TRUNNELSOURCES)
+src_trunnel_libor_trunnel_a_CPPFLAGS = -DTRUNNEL_LOCAL_H $(AM_CPPFLAGS)
+
+src_trunnel_libor_trunnel_testing_a_SOURCES = $(TRUNNELSOURCES)
+src_trunnel_libor_trunnel_testing_a_CPPFLAGS = -DTOR_UNIT_TESTS -DTRUNNEL_LOCAL_H $(AM_CPPFLAGS)
+src_trunnel_libor_trunnel_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
+
+noinst_HEADERS+= $(TRUNNELHEADERS)
diff --git a/src/trunnel/pwbox.c b/src/trunnel/pwbox.c
new file mode 100644
index 0000000000..bfea3ac671
--- /dev/null
+++ b/src/trunnel/pwbox.c
@@ -0,0 +1,515 @@
+/* pwbox.c -- generated by Trunnel v1.2.
+ * https://gitweb.torproject.org/trunnel.git
+ * You probably shouldn't edit this file.
+ */
+#include <stdlib.h>
+#include "trunnel-impl.h"
+
+#include "pwbox.h"
+
+#define TRUNNEL_SET_ERROR_CODE(obj) \
+ do { \
+ (obj)->trunnel_error_code_ = 1; \
+ } while (0)
+
+#if defined(__COVERITY__) || defined(__clang_analyzer__)
+/* If we're runnning a static analysis tool, we don't want it to complain
+ * that some of our remaining-bytes checks are dead-code. */
+int pwbox_deadcode_dummy__ = 0;
+#define OR_DEADCODE_DUMMY || pwbox_deadcode_dummy__
+#else
+#define OR_DEADCODE_DUMMY
+#endif
+
+#define CHECK_REMAINING(nbytes, label) \
+ do { \
+ if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
+ goto label; \
+ } \
+ } while (0)
+
+pwbox_encoded_t *
+pwbox_encoded_new(void)
+{
+ pwbox_encoded_t *val = trunnel_calloc(1, sizeof(pwbox_encoded_t));
+ if (NULL == val)
+ return NULL;
+ val->fixedbytes0 = PWBOX0_CONST0;
+ val->fixedbytes1 = PWBOX0_CONST1;
+ return val;
+}
+
+/** Release all storage held inside 'obj', but do not free 'obj'.
+ */
+static void
+pwbox_encoded_clear(pwbox_encoded_t *obj)
+{
+ (void) obj;
+ TRUNNEL_DYNARRAY_WIPE(&obj->skey_header);
+ TRUNNEL_DYNARRAY_CLEAR(&obj->skey_header);
+ TRUNNEL_DYNARRAY_WIPE(&obj->data);
+ TRUNNEL_DYNARRAY_CLEAR(&obj->data);
+}
+
+void
+pwbox_encoded_free(pwbox_encoded_t *obj)
+{
+ if (obj == NULL)
+ return;
+ pwbox_encoded_clear(obj);
+ trunnel_memwipe(obj, sizeof(pwbox_encoded_t));
+ trunnel_free_(obj);
+}
+
+uint32_t
+pwbox_encoded_get_fixedbytes0(pwbox_encoded_t *inp)
+{
+ return inp->fixedbytes0;
+}
+int
+pwbox_encoded_set_fixedbytes0(pwbox_encoded_t *inp, uint32_t val)
+{
+ if (! ((val == PWBOX0_CONST0))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->fixedbytes0 = val;
+ return 0;
+}
+uint32_t
+pwbox_encoded_get_fixedbytes1(pwbox_encoded_t *inp)
+{
+ return inp->fixedbytes1;
+}
+int
+pwbox_encoded_set_fixedbytes1(pwbox_encoded_t *inp, uint32_t val)
+{
+ if (! ((val == PWBOX0_CONST1))) {
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+ }
+ inp->fixedbytes1 = val;
+ return 0;
+}
+uint8_t
+pwbox_encoded_get_header_len(pwbox_encoded_t *inp)
+{
+ return inp->header_len;
+}
+int
+pwbox_encoded_set_header_len(pwbox_encoded_t *inp, uint8_t val)
+{
+ inp->header_len = val;
+ return 0;
+}
+size_t
+pwbox_encoded_getlen_skey_header(const pwbox_encoded_t *inp)
+{
+ return TRUNNEL_DYNARRAY_LEN(&inp->skey_header);
+}
+
+uint8_t
+pwbox_encoded_get_skey_header(pwbox_encoded_t *inp, size_t idx)
+{
+ return TRUNNEL_DYNARRAY_GET(&inp->skey_header, idx);
+}
+
+int
+pwbox_encoded_set_skey_header(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
+{
+ TRUNNEL_DYNARRAY_SET(&inp->skey_header, idx, elt);
+ return 0;
+}
+int
+pwbox_encoded_add_skey_header(pwbox_encoded_t *inp, uint8_t elt)
+{
+#if SIZE_MAX >= UINT8_MAX
+ if (inp->skey_header.n_ == UINT8_MAX)
+ goto trunnel_alloc_failed;
+#endif
+ TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->skey_header, elt, {});
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+
+uint8_t *
+pwbox_encoded_getarray_skey_header(pwbox_encoded_t *inp)
+{
+ return inp->skey_header.elts_;
+}
+int
+pwbox_encoded_setlen_skey_header(pwbox_encoded_t *inp, size_t newlen)
+{
+ uint8_t *newptr;
+#if UINT8_MAX < SIZE_MAX
+ if (newlen > UINT8_MAX)
+ goto trunnel_alloc_failed;
+#endif
+ newptr = trunnel_dynarray_setlen(&inp->skey_header.allocated_,
+ &inp->skey_header.n_, inp->skey_header.elts_, newlen,
+ sizeof(inp->skey_header.elts_[0]), (trunnel_free_fn_t) NULL,
+ &inp->trunnel_error_code_);
+ if (newptr == NULL)
+ goto trunnel_alloc_failed;
+ inp->skey_header.elts_ = newptr;
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+size_t
+pwbox_encoded_getlen_iv(const pwbox_encoded_t *inp)
+{
+ (void)inp; return 16;
+}
+
+uint8_t
+pwbox_encoded_get_iv(const pwbox_encoded_t *inp, size_t idx)
+{
+ trunnel_assert(idx < 16);
+ return inp->iv[idx];
+}
+
+int
+pwbox_encoded_set_iv(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
+{
+ trunnel_assert(idx < 16);
+ inp->iv[idx] = elt;
+ return 0;
+}
+
+uint8_t *
+pwbox_encoded_getarray_iv(pwbox_encoded_t *inp)
+{
+ return inp->iv;
+}
+size_t
+pwbox_encoded_getlen_data(const pwbox_encoded_t *inp)
+{
+ return TRUNNEL_DYNARRAY_LEN(&inp->data);
+}
+
+uint8_t
+pwbox_encoded_get_data(pwbox_encoded_t *inp, size_t idx)
+{
+ return TRUNNEL_DYNARRAY_GET(&inp->data, idx);
+}
+
+int
+pwbox_encoded_set_data(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
+{
+ TRUNNEL_DYNARRAY_SET(&inp->data, idx, elt);
+ return 0;
+}
+int
+pwbox_encoded_add_data(pwbox_encoded_t *inp, uint8_t elt)
+{
+ TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->data, elt, {});
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+
+uint8_t *
+pwbox_encoded_getarray_data(pwbox_encoded_t *inp)
+{
+ return inp->data.elts_;
+}
+int
+pwbox_encoded_setlen_data(pwbox_encoded_t *inp, size_t newlen)
+{
+ uint8_t *newptr;
+ newptr = trunnel_dynarray_setlen(&inp->data.allocated_,
+ &inp->data.n_, inp->data.elts_, newlen,
+ sizeof(inp->data.elts_[0]), (trunnel_free_fn_t) NULL,
+ &inp->trunnel_error_code_);
+ if (newptr == NULL)
+ goto trunnel_alloc_failed;
+ inp->data.elts_ = newptr;
+ return 0;
+ trunnel_alloc_failed:
+ TRUNNEL_SET_ERROR_CODE(inp);
+ return -1;
+}
+size_t
+pwbox_encoded_getlen_hmac(const pwbox_encoded_t *inp)
+{
+ (void)inp; return 32;
+}
+
+uint8_t
+pwbox_encoded_get_hmac(const pwbox_encoded_t *inp, size_t idx)
+{
+ trunnel_assert(idx < 32);
+ return inp->hmac[idx];
+}
+
+int
+pwbox_encoded_set_hmac(pwbox_encoded_t *inp, size_t idx, uint8_t elt)
+{
+ trunnel_assert(idx < 32);
+ inp->hmac[idx] = elt;
+ return 0;
+}
+
+uint8_t *
+pwbox_encoded_getarray_hmac(pwbox_encoded_t *inp)
+{
+ return inp->hmac;
+}
+const char *
+pwbox_encoded_check(const pwbox_encoded_t *obj)
+{
+ if (obj == NULL)
+ return "Object was NULL";
+ if (obj->trunnel_error_code_)
+ return "A set function failed on this object";
+ if (! (obj->fixedbytes0 == PWBOX0_CONST0))
+ return "Integer out of bounds";
+ if (! (obj->fixedbytes1 == PWBOX0_CONST1))
+ return "Integer out of bounds";
+ if (TRUNNEL_DYNARRAY_LEN(&obj->skey_header) != obj->header_len)
+ return "Length mismatch for skey_header";
+ return NULL;
+}
+
+ssize_t
+pwbox_encoded_encoded_len(const pwbox_encoded_t *obj)
+{
+ ssize_t result = 0;
+
+ if (NULL != pwbox_encoded_check(obj))
+ return -1;
+
+
+ /* Length of u32 fixedbytes0 IN [PWBOX0_CONST0] */
+ result += 4;
+
+ /* Length of u32 fixedbytes1 IN [PWBOX0_CONST1] */
+ result += 4;
+
+ /* Length of u8 header_len */
+ result += 1;
+
+ /* Length of u8 skey_header[header_len] */
+ result += TRUNNEL_DYNARRAY_LEN(&obj->skey_header);
+
+ /* Length of u8 iv[16] */
+ result += 16;
+
+ /* Length of u8 data[] */
+ result += TRUNNEL_DYNARRAY_LEN(&obj->data);
+
+ /* Length of u8 hmac[32] */
+ result += 32;
+ return result;
+}
+int
+pwbox_encoded_clear_errors(pwbox_encoded_t *obj)
+{
+ int r = obj->trunnel_error_code_;
+ obj->trunnel_error_code_ = 0;
+ return r;
+}
+ssize_t
+pwbox_encoded_encode(uint8_t *output, size_t avail, const pwbox_encoded_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 = pwbox_encoded_encoded_len(obj);
+#endif
+ int enforce_avail = 0;
+ const size_t avail_orig = avail;
+
+ if (NULL != (msg = pwbox_encoded_check(obj)))
+ goto check_failed;
+
+#ifdef TRUNNEL_CHECK_ENCODED_LEN
+ trunnel_assert(encoded_len >= 0);
+#endif
+
+ /* Encode u32 fixedbytes0 IN [PWBOX0_CONST0] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 4)
+ goto truncated;
+ trunnel_set_uint32(ptr, trunnel_htonl(obj->fixedbytes0));
+ written += 4; ptr += 4;
+
+ /* Encode u32 fixedbytes1 IN [PWBOX0_CONST1] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 4)
+ goto truncated;
+ trunnel_set_uint32(ptr, trunnel_htonl(obj->fixedbytes1));
+ written += 4; ptr += 4;
+
+ /* Encode u8 header_len */
+ trunnel_assert(written <= avail);
+ if (avail - written < 1)
+ goto truncated;
+ trunnel_set_uint8(ptr, (obj->header_len));
+ written += 1; ptr += 1;
+
+ /* Encode u8 skey_header[header_len] */
+ {
+ size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->skey_header);
+ trunnel_assert(obj->header_len == elt_len);
+ trunnel_assert(written <= avail);
+ if (avail - written < elt_len)
+ goto truncated;
+ memcpy(ptr, obj->skey_header.elts_, elt_len);
+ written += elt_len; ptr += elt_len;
+ }
+
+ /* Encode u8 iv[16] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 16)
+ goto truncated;
+ memcpy(ptr, obj->iv, 16);
+ written += 16; ptr += 16;
+ {
+
+ /* Encode u8 data[] */
+ {
+ size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->data);
+ trunnel_assert(written <= avail);
+ if (avail - written < elt_len)
+ goto truncated;
+ memcpy(ptr, obj->data.elts_, elt_len);
+ written += elt_len; ptr += elt_len;
+ }
+ trunnel_assert(written <= avail);
+ if (avail - written < 32)
+ goto truncated;
+ avail = written + 32;
+ enforce_avail = 1;
+ }
+
+ /* Encode u8 hmac[32] */
+ trunnel_assert(written <= avail);
+ if (avail - written < 32) {
+ if (avail_orig - written < 32)
+ goto truncated;
+ else
+ goto check_failed;
+ }
+ memcpy(ptr, obj->hmac, 32);
+ written += 32; ptr += 32;
+
+
+ trunnel_assert(ptr == output + written);
+ if (enforce_avail && avail != written)
+ goto check_failed;
+#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 pwbox_encoded_parse(), but do not allocate the output object.
+ */
+static ssize_t
+pwbox_encoded_parse_into(pwbox_encoded_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 u32 fixedbytes0 IN [PWBOX0_CONST0] */
+ CHECK_REMAINING(4, truncated);
+ obj->fixedbytes0 = trunnel_ntohl(trunnel_get_uint32(ptr));
+ remaining -= 4; ptr += 4;
+ if (! (obj->fixedbytes0 == PWBOX0_CONST0))
+ goto fail;
+
+ /* Parse u32 fixedbytes1 IN [PWBOX0_CONST1] */
+ CHECK_REMAINING(4, truncated);
+ obj->fixedbytes1 = trunnel_ntohl(trunnel_get_uint32(ptr));
+ remaining -= 4; ptr += 4;
+ if (! (obj->fixedbytes1 == PWBOX0_CONST1))
+ goto fail;
+
+ /* Parse u8 header_len */
+ CHECK_REMAINING(1, truncated);
+ obj->header_len = (trunnel_get_uint8(ptr));
+ remaining -= 1; ptr += 1;
+
+ /* Parse u8 skey_header[header_len] */
+ CHECK_REMAINING(obj->header_len, truncated);
+ TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->skey_header, obj->header_len, {});
+ obj->skey_header.n_ = obj->header_len;
+ memcpy(obj->skey_header.elts_, ptr, obj->header_len);
+ ptr += obj->header_len; remaining -= obj->header_len;
+
+ /* Parse u8 iv[16] */
+ CHECK_REMAINING(16, truncated);
+ memcpy(obj->iv, ptr, 16);
+ remaining -= 16; ptr += 16;
+ {
+ size_t remaining_after;
+ CHECK_REMAINING(32, truncated);
+ remaining_after = 32;
+ remaining = remaining - 32;
+
+ /* Parse u8 data[] */
+ TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->data, remaining, {});
+ obj->data.n_ = remaining;
+ memcpy(obj->data.elts_, ptr, remaining);
+ ptr += remaining; remaining -= remaining;
+ if (remaining != 0)
+ goto fail;
+ remaining = remaining_after;
+ }
+
+ /* Parse u8 hmac[32] */
+ CHECK_REMAINING(32, truncated);
+ memcpy(obj->hmac, ptr, 32);
+ remaining -= 32; ptr += 32;
+ 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
+pwbox_encoded_parse(pwbox_encoded_t **output, const uint8_t *input, const size_t len_in)
+{
+ ssize_t result;
+ *output = pwbox_encoded_new();
+ if (NULL == *output)
+ return -1;
+ result = pwbox_encoded_parse_into(*output, input, len_in);
+ if (result < 0) {
+ pwbox_encoded_free(*output);
+ *output = NULL;
+ }
+ return result;
+}
diff --git a/src/trunnel/pwbox.h b/src/trunnel/pwbox.h
new file mode 100644
index 0000000000..5b170eb45e
--- /dev/null
+++ b/src/trunnel/pwbox.h
@@ -0,0 +1,173 @@
+/* pwbox.h -- generated by by Trunnel v1.2.
+ * https://gitweb.torproject.org/trunnel.git
+ * You probably shouldn't edit this file.
+ */
+#ifndef TRUNNEL_PWBOX_H
+#define TRUNNEL_PWBOX_H
+
+#include <stdint.h>
+#include "trunnel.h"
+
+#define PWBOX0_CONST0 1414484546
+#define PWBOX0_CONST1 1331179568
+#if !defined(TRUNNEL_OPAQUE) && !defined(TRUNNEL_OPAQUE_PWBOX_ENCODED)
+struct pwbox_encoded_st {
+ uint32_t fixedbytes0;
+ uint32_t fixedbytes1;
+ uint8_t header_len;
+ TRUNNEL_DYNARRAY_HEAD(, uint8_t) skey_header;
+ uint8_t iv[16];
+ TRUNNEL_DYNARRAY_HEAD(, uint8_t) data;
+ uint8_t hmac[32];
+ uint8_t trunnel_error_code_;
+};
+#endif
+typedef struct pwbox_encoded_st pwbox_encoded_t;
+/** Return a newly allocated pwbox_encoded with all elements set to
+ * zero.
+ */
+pwbox_encoded_t *pwbox_encoded_new(void);
+/** Release all storage held by the pwbox_encoded in 'victim'. (Do
+ * nothing if 'victim' is NULL.)
+ */
+void pwbox_encoded_free(pwbox_encoded_t *victim);
+/** Try to parse a pwbox_encoded 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
+ * pwbox_encoded_t. On failure, return -2 if the input appears
+ * truncated, and -1 if the input is otherwise invalid.
+ */
+ssize_t pwbox_encoded_parse(pwbox_encoded_t **output, const uint8_t *input, const size_t len_in);
+/** Return the number of bytes we expect to need to encode the
+ * pwbox_encoded 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 pwbox_encoded_encoded_len(const pwbox_encoded_t *obj);
+/** Try to encode the pwbox_encoded 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 pwbox_encoded_encode(uint8_t *output, const size_t avail, const pwbox_encoded_t *input);
+/** Check whether the internal state of the pwbox_encoded in 'obj' is
+ * consistent. Return NULL if it is, and a short message if it is not.
+ */
+const char *pwbox_encoded_check(const pwbox_encoded_t *obj);
+/** Clear any errors that were set on the object 'obj' by its setter
+ * functions. Return true iff errors were cleared.
+ */
+int pwbox_encoded_clear_errors(pwbox_encoded_t *obj);
+/** Return the value of the fixedbytes0 field of the pwbox_encoded_t
+ * in 'inp'
+ */
+uint32_t pwbox_encoded_get_fixedbytes0(pwbox_encoded_t *inp);
+/** Set the value of the fixedbytes0 field of the pwbox_encoded_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int pwbox_encoded_set_fixedbytes0(pwbox_encoded_t *inp, uint32_t val);
+/** Return the value of the fixedbytes1 field of the pwbox_encoded_t
+ * in 'inp'
+ */
+uint32_t pwbox_encoded_get_fixedbytes1(pwbox_encoded_t *inp);
+/** Set the value of the fixedbytes1 field of the pwbox_encoded_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int pwbox_encoded_set_fixedbytes1(pwbox_encoded_t *inp, uint32_t val);
+/** Return the value of the header_len field of the pwbox_encoded_t in
+ * 'inp'
+ */
+uint8_t pwbox_encoded_get_header_len(pwbox_encoded_t *inp);
+/** Set the value of the header_len field of the pwbox_encoded_t in
+ * 'inp' to 'val'. Return 0 on success; return -1 and set the error
+ * code on 'inp' on failure.
+ */
+int pwbox_encoded_set_header_len(pwbox_encoded_t *inp, uint8_t val);
+/** Return the length of the dynamic array holding the skey_header
+ * field of the pwbox_encoded_t in 'inp'.
+ */
+size_t pwbox_encoded_getlen_skey_header(const pwbox_encoded_t *inp);
+/** Return the element at position 'idx' of the dynamic array field
+ * skey_header of the pwbox_encoded_t in 'inp'.
+ */
+uint8_t pwbox_encoded_get_skey_header(pwbox_encoded_t *inp, size_t idx);
+/** Change the element at position 'idx' of the dynamic array field
+ * skey_header of the pwbox_encoded_t in 'inp', so that it will hold
+ * the value 'elt'.
+ */
+int pwbox_encoded_set_skey_header(pwbox_encoded_t *inp, size_t idx, uint8_t elt);
+/** Append a new element 'elt' to the dynamic array field skey_header
+ * of the pwbox_encoded_t in 'inp'.
+ */
+int pwbox_encoded_add_skey_header(pwbox_encoded_t *inp, uint8_t elt);
+/** Return a pointer to the variable-length array field skey_header of
+ * 'inp'.
+ */
+uint8_t * pwbox_encoded_getarray_skey_header(pwbox_encoded_t *inp);
+/** Change the length of the variable-length array field skey_header
+ * 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 pwbox_encoded_setlen_skey_header(pwbox_encoded_t *inp, size_t newlen);
+/** Return the (constant) length of the array holding the iv field of
+ * the pwbox_encoded_t in 'inp'.
+ */
+size_t pwbox_encoded_getlen_iv(const pwbox_encoded_t *inp);
+/** Return the element at position 'idx' of the fixed array field iv
+ * of the pwbox_encoded_t in 'inp'.
+ */
+uint8_t pwbox_encoded_get_iv(const pwbox_encoded_t *inp, size_t idx);
+/** Change the element at position 'idx' of the fixed array field iv
+ * of the pwbox_encoded_t in 'inp', so that it will hold the value
+ * 'elt'.
+ */
+int pwbox_encoded_set_iv(pwbox_encoded_t *inp, size_t idx, uint8_t elt);
+/** Return a pointer to the 16-element array field iv of 'inp'.
+ */
+uint8_t * pwbox_encoded_getarray_iv(pwbox_encoded_t *inp);
+/** Return the length of the dynamic array holding the data field of
+ * the pwbox_encoded_t in 'inp'.
+ */
+size_t pwbox_encoded_getlen_data(const pwbox_encoded_t *inp);
+/** Return the element at position 'idx' of the dynamic array field
+ * data of the pwbox_encoded_t in 'inp'.
+ */
+uint8_t pwbox_encoded_get_data(pwbox_encoded_t *inp, size_t idx);
+/** Change the element at position 'idx' of the dynamic array field
+ * data of the pwbox_encoded_t in 'inp', so that it will hold the
+ * value 'elt'.
+ */
+int pwbox_encoded_set_data(pwbox_encoded_t *inp, size_t idx, uint8_t elt);
+/** Append a new element 'elt' to the dynamic array field data of the
+ * pwbox_encoded_t in 'inp'.
+ */
+int pwbox_encoded_add_data(pwbox_encoded_t *inp, uint8_t elt);
+/** Return a pointer to the variable-length array field data of 'inp'.
+ */
+uint8_t * pwbox_encoded_getarray_data(pwbox_encoded_t *inp);
+/** Change the length of the variable-length array field data 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 pwbox_encoded_setlen_data(pwbox_encoded_t *inp, size_t newlen);
+/** Return the (constant) length of the array holding the hmac field
+ * of the pwbox_encoded_t in 'inp'.
+ */
+size_t pwbox_encoded_getlen_hmac(const pwbox_encoded_t *inp);
+/** Return the element at position 'idx' of the fixed array field hmac
+ * of the pwbox_encoded_t in 'inp'.
+ */
+uint8_t pwbox_encoded_get_hmac(const pwbox_encoded_t *inp, size_t idx);
+/** Change the element at position 'idx' of the fixed array field hmac
+ * of the pwbox_encoded_t in 'inp', so that it will hold the value
+ * 'elt'.
+ */
+int pwbox_encoded_set_hmac(pwbox_encoded_t *inp, size_t idx, uint8_t elt);
+/** Return a pointer to the 32-element array field hmac of 'inp'.
+ */
+uint8_t * pwbox_encoded_getarray_hmac(pwbox_encoded_t *inp);
+
+
+#endif
diff --git a/src/trunnel/pwbox.trunnel b/src/trunnel/pwbox.trunnel
new file mode 100644
index 0000000000..10db74b4e5
--- /dev/null
+++ b/src/trunnel/pwbox.trunnel
@@ -0,0 +1,14 @@
+
+const PWBOX0_CONST0 = 0x544f5242; // TORB
+const PWBOX0_CONST1 = 0x4f583030; // OX00
+
+struct pwbox_encoded {
+ u32 fixedbytes0 IN [PWBOX0_CONST0];
+ u32 fixedbytes1 IN [PWBOX0_CONST1];
+ u8 header_len;
+ u8 skey_header[header_len];
+ u8 iv[16];
+ u8 data[..-32];
+ u8 hmac[32];
+};
+
diff --git a/src/trunnel/trunnel-local.h b/src/trunnel/trunnel-local.h
new file mode 100644
index 0000000000..b7c2ab98ef
--- /dev/null
+++ b/src/trunnel/trunnel-local.h
@@ -0,0 +1,18 @@
+
+#ifndef TRUNNEL_LOCAL_H_INCLUDED
+#define TRUNNEL_LOCAL_H_INCLUDED
+
+#include "util.h"
+#include "compat.h"
+#include "crypto.h"
+
+#define trunnel_malloc tor_malloc
+#define trunnel_calloc tor_calloc
+#define trunnel_strdup tor_strdup
+#define trunnel_free_ tor_free_
+#define trunnel_realloc tor_realloc
+#define trunnel_reallocarray tor_reallocarray
+#define trunnel_assert tor_assert
+#define trunnel_memwipe(mem, len) memwipe((mem), 0, (len))
+
+#endif