Loading .gitignore +6 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ .dirstamp # Stuff made by our makefiles *.bak # Python droppings *.pyc # / /Makefile Loading Loading @@ -130,6 +132,8 @@ /src/common/libor-crypto.lib /src/common/libor-event.a /src/common/libor-event.lib /src/common/libcurve25519_donna.a /src/common/libcurve25519_donna.lib # /src/config/ /src/config/Makefile Loading @@ -154,9 +158,10 @@ /src/test/bench.exe /src/test/test /src/test/test-child /src/test/test-ntor-cl /src/test/test.exe /src/test/test-child.exe /src/test/test-ntor-cl.exe # /src/tools/ /src/tools/tor-checkkey Loading changes/ntor 0 → 100644 +40 −0 Original line number Diff line number Diff line o Major features: - Tor now supports a new circuit extension handshake designed by Ian Goldberg, Douglas Stebila, and Berkant Ustaoglu. Our original circuit extension handshake, later called "TAP", was a bit slow (especially on the server side), had a fragile security proof, and used weaker keys than we'd now prefer. The new circuit handshake uses Dan Bernstein's "curve25519" elliptic-curve Diffie-Hellman function, making it significantly more secure than the older handshake, and significantly faster. Tor can either use one of two built-in pure-C curve25519-donna implementations by Adam Langley, or link against the "nacl" library for a tuned version if present. The built-in version is very fast for 64-bit systems building with GCC. (About 10-14x faster on the server side, and about 7x faster on the client side.) The built-in 32-bit version is still faster than the old TAP protocol (about 3x), but using libnacl would be better on most 32-bit x86 hosts. Clients don't currently use this protocol by default, since comparatively few clients support it so far. To try it, set UseNTorHandshake to 1. Implements proposal 216; closes ticket #7202. - Tor servers and clients now support a better CREATE/EXTEND cell format, allowing the sender to specify multiple address, identity, and handshake types. Implements Robert Ransom's proposal 200; closes ticket #7199. o Code simplification and refactoring: - Split the onion.c file into separate modules for the onion queue and the different handshakes it supports. - Remove the marshalling/unmarshalling code for sending requests to cpuworkers over a socket, and instead just send structs. The recipient will always be the same Tor binary as the sender, so any encoding is overkill. o Testing: - Add benchmark functions to test onion handshake performance. configure.ac +99 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ AC_ARG_ENABLE(static-zlib, AS_HELP_STRING(--enable-static-zlib, Link against a static zlib library. Requires --with-zlib-dir)) AC_ARG_ENABLE(static-tor, AS_HELP_STRING(--enable-static-tor, Create an entirely static Tor binary. Requires --with-openssl-dir and --with-libevent-dir and --with-zlib-dir)) AC_ARG_ENABLE(curve25519, AS_HELP_STRING(--disable-curve25519, Build Tor with no curve25519 elliptic-curve crypto support)) if test "$enable_static_tor" = "yes"; then enable_static_libevent="yes"; Loading Loading @@ -639,6 +641,103 @@ if test "$upnp" = "true"; then fi fi dnl ============================================================ dnl We need an implementation of curve25519. dnl set these defaults. have_a_curve25519=no build_curve25519_donna=no build_curve25519_donna_c64=no use_curve25519_donna=no use_curve25519_nacl=no CURVE25519_LIBS= if test x$enable_curve25519 != xno; then dnl The best choice is using curve25519-donna-c64, but that requires dnl that we AC_CACHE_CHECK([whether we can use curve25519-donna-c64], tor_cv_can_use_curve25519_donna_c64, [AC_RUN_IFELSE( [AC_LANG_PROGRAM([dnl #include <stdint.h> typedef unsigned uint128_t __attribute__((mode(TI))); ], [dnl uint64_t a = ((uint64_t)2000000000) * 1000000000; uint64_t b = ((uint64_t)1234567890) << 24; uint128_t c = ((uint128_t)a) * b; return ((uint64_t)(c>>96)) == 522859 && ((uint64_t)(c>>64))&0xffffffffL == 3604448702L && ((uint64_t)(c>>32))&0xffffffffL == 2351960064L && ((uint64_t)(c))&0xffffffffL == 0; ])], [tor_cv_can_use_curve25519_donna_c64=yes], [tor_cv_can_use_curve25519_donna_c64=no], [AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([dnl #include <stdint.h> typedef unsigned uint128_t __attribute__((mode(TI))); ], [dnl uint64_t a = ((uint64_t)2000000000) * 1000000000; uint64_t b = ((uint64_t)1234567890) << 24; uint128_t c = ((uint128_t)a) * b; return ((uint64_t)(c>>96)) == 522859 && ((uint64_t)(c>>64))&0xffffffffL == 3604448702L && ((uint64_t)(c>>32))&0xffffffffL == 2351960064L && ((uint64_t)(c))&0xffffffffL == 0; ])], [tor_cv_can_use_curve25519_donna_c64=cross], [tor_cv_can_use_curve25519_donna_c64=no])])]) AC_CACHE_CHECK([whether we can use curve25519 from nacl], tor_cv_can_use_curve25519_nacl, [tor_saved_LIBS="$LIBS" LIBS="$LIBS -lnacl" AC_LINK_IFELSE( [AC_LANG_PROGRAM([dnl #include <crypto_scalarmult_curve25519.h> #ifdef crypto_scalarmult_curve25519_ref_BYTES #error Hey, this is the reference implementation! #endif ], [ unsigned char *a, *b, *c; crypto_scalarmult_curve25519(a,b,c); ])], [tor_cv_can_use_curve25519_nacl=yes], [tor_cv_can_use_curve25519_nacl=no]) LIBS="$tor_saved_LIBS" ]) dnl Okay, now we need to figure out which one to actually use. Fall back dnl to curve25519-donna.c if test x$tor_cv_can_use_curve25519_donna_c64 != xno; then build_curve25519_donna_c64=yes use_curve25519_donna=yes elif test x$tor_cv_can_use_curve25519_nacl = xyes; then use_curve25519_nacl=yes CURVE25519_LIBS=-lnacl else build_curve25519_donna=yes use_curve25519_donna=yes fi have_a_curve25519=yes fi if test x$have_a_curve25519 = xyes; then AC_DEFINE(CURVE25519_ENABLED, 1, [Defined if we have a curve25519 implementation]) fi if test x$use_curve25519_donna = xyes; then AC_DEFINE(USE_CURVE25519_DONNA, 1, [Defined if we should use an internal curve25519_donna{,_c64} implementation]) fi if test x$use_curve25519_nacl = xyes; then AC_DEFINE(USE_CURVE25519_NACL, 1, [Defined if we should use a curve25519 from nacl]) fi AM_CONDITIONAL(BUILD_CURVE25519_DONNA, test x$build_curve25519_donna = xyes) AM_CONDITIONAL(BUILD_CURVE25519_DONNA_C64, test x$build_curve25519_donna_c64 = xyes) AM_CONDITIONAL(CURVE25519_ENABLED, test x$have_a_curve25519 = xyes) AC_SUBST(CURVE25519_LIBS) dnl Make sure to enable support for large off_t if available. AC_SYS_LARGEFILE Loading doc/tor.1.txt +10 −0 Original line number Diff line number Diff line Loading @@ -1218,6 +1218,16 @@ The following options are useful only for clients (that is, if "auto" (recommended) then it is on for all clients that do not set FetchUselessDescriptors. (Default: auto) **UseNTorHandshake** **0**|**1**|**auto**:: The "ntor" circuit-creation handshake is faster and (we think) more secure than the original ("TAP") circuit handshake, but starting to use it too early might make your client stand out. If this option is 0, your Tor client won't use the ntor handshake. If it's 1, your Tor client will use the ntor handshake to extend circuits through servers that support it. If this option is "auto" (recommended), then your client will use the ntor handshake once enough directory authorities recommend it. (Default: auto) **PathBiasCircThreshold** __NUM__ + **PathBiasNoticeRate** __NUM__ + Loading src/common/crypto.c +124 −39 Original line number Diff line number Diff line Loading @@ -2036,6 +2036,16 @@ crypto_dh_new(int dh_type) return NULL; } /** Return a copy of <b>dh</b>, sharing its internal state. */ crypto_dh_t * crypto_dh_dup(const crypto_dh_t *dh) { crypto_dh_t *dh_new = tor_malloc_zero(sizeof(crypto_dh_t)); dh_new->dh = dh->dh; DH_up_ref(dh->dh); return dh_new; } /** Return the length of the DH key in <b>dh</b>, in bytes. */ int Loading Loading @@ -2174,8 +2184,8 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh, goto error; } secret_len = result; if (crypto_expand_key_material(secret_tmp, secret_len, secret_out, secret_bytes_out)<0) if (crypto_expand_key_material_TAP((uint8_t*)secret_tmp, secret_len, (uint8_t*)secret_out, secret_bytes_out)<0) goto error; secret_len = secret_bytes_out; Loading @@ -2201,15 +2211,18 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh, * <b>key_out</b> by taking the first <b>key_out_len</b> bytes of * H(K | [00]) | H(K | [01]) | .... * * This is the key expansion algorithm used in the "TAP" circuit extension * mechanism; it shouldn't be used for new protocols. * * Return 0 on success, -1 on failure. */ int crypto_expand_key_material(const char *key_in, size_t key_in_len, char *key_out, size_t key_out_len) crypto_expand_key_material_TAP(const uint8_t *key_in, size_t key_in_len, uint8_t *key_out, size_t key_out_len) { int i; char *cp, *tmp = tor_malloc(key_in_len+1); char digest[DIGEST_LEN]; uint8_t *cp, *tmp = tor_malloc(key_in_len+1); uint8_t digest[DIGEST_LEN]; /* If we try to get more than this amount of key data, we'll repeat blocks.*/ tor_assert(key_out_len <= DIGEST_LEN*256); Loading @@ -2218,7 +2231,7 @@ crypto_expand_key_material(const char *key_in, size_t key_in_len, for (cp = key_out, i=0; cp < key_out+key_out_len; ++i, cp += DIGEST_LEN) { tmp[key_in_len] = i; if (crypto_digest(digest, tmp, key_in_len+1)) if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1)) goto err; memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out))); } Loading @@ -2234,6 +2247,65 @@ crypto_expand_key_material(const char *key_in, size_t key_in_len, return -1; } /** Expand some secret key material according to RFC5869, using SHA256 as the * underlying hash. The <b>key_in_len</b> bytes at <b>key_in</b> are the * secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the * <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt" * and "info" parameters respectively. On success, write <b>key_out_len</b> * bytes to <b>key_out</b> and return 0. On failure, return -1. */ int crypto_expand_key_material_rfc5869_sha256( const uint8_t *key_in, size_t key_in_len, const uint8_t *salt_in, size_t salt_in_len, const uint8_t *info_in, size_t info_in_len, uint8_t *key_out, size_t key_out_len) { uint8_t prk[DIGEST256_LEN]; uint8_t tmp[DIGEST256_LEN + 128 + 1]; uint8_t mac[DIGEST256_LEN]; int i; uint8_t *outp; size_t tmp_len; crypto_hmac_sha256((char*)prk, (const char*)salt_in, salt_in_len, (const char*)key_in, key_in_len); /* If we try to get more than this amount of key data, we'll repeat blocks.*/ tor_assert(key_out_len <= DIGEST256_LEN * 256); tor_assert(info_in_len <= 128); memset(tmp, 0, sizeof(tmp)); outp = key_out; i = 1; while (key_out_len) { size_t n; if (i > 1) { memcpy(tmp, mac, DIGEST256_LEN); memcpy(tmp+DIGEST256_LEN, info_in, info_in_len); tmp[DIGEST256_LEN+info_in_len] = i; tmp_len = DIGEST256_LEN + info_in_len + 1; } else { memcpy(tmp, info_in, info_in_len); tmp[info_in_len] = i; tmp_len = info_in_len + 1; } crypto_hmac_sha256((char*)mac, (const char*)prk, DIGEST256_LEN, (const char*)tmp, tmp_len); n = key_out_len < DIGEST256_LEN ? key_out_len : DIGEST256_LEN; memcpy(outp, mac, n); key_out_len -= n; outp += n; ++i; } memwipe(tmp, 0, sizeof(tmp)); memwipe(mac, 0, sizeof(mac)); return 0; } /** Free a DH key exchange object. */ void Loading Loading @@ -2272,22 +2344,16 @@ seed_weak_rng(void) tor_init_weak_random(seed); } /** Seed OpenSSL's random number generator with bytes from the operating * system. <b>startup</b> should be true iff we have just started Tor and * have not yet allocated a bunch of fds. Return 0 on success, -1 on failure. /** Try to get <b>out_len</b> bytes of the strongest entropy we can generate, * storing it into <b>out</b>. */ int crypto_seed_rng(int startup) crypto_strongest_rand(uint8_t *out, size_t out_len) { int rand_poll_status = 0; /* local variables */ #ifdef _WIN32 unsigned char buf[ADD_ENTROPY]; static int provider_set = 0; static HCRYPTPROV provider; #else char buf[ADD_ENTROPY]; static const char *filenames[] = { "/dev/srandom", "/dev/urandom", "/dev/random", NULL }; Loading @@ -2295,58 +2361,77 @@ crypto_seed_rng(int startup) size_t n; #endif /* OpenSSL has a RAND_poll function that knows about more kinds of * entropy than we do. We'll try calling that, *and* calling our own entropy * functions. If one succeeds, we'll accept the RNG as seeded. */ if (startup || RAND_POLL_IS_SAFE) { rand_poll_status = RAND_poll(); if (rand_poll_status == 0) log_warn(LD_CRYPTO, "RAND_poll() failed."); } #ifdef _WIN32 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 rand_poll_status ? 0 : -1; return -1; } } provider_set = 1; } if (!CryptGenRandom(provider, sizeof(buf), buf)) { if (!CryptGenRandom(provider, out_len, out)) { log_warn(LD_CRYPTO, "Can't get entropy from CryptoAPI."); return rand_poll_status ? 0 : -1; return -1; } RAND_seed(buf, sizeof(buf)); memwipe(buf, 0, sizeof(buf)); seed_weak_rng(); return 0; #else for (i = 0; filenames[i]; ++i) { fd = open(filenames[i], O_RDONLY, 0); if (fd<0) continue; log_info(LD_CRYPTO, "Seeding RNG from \"%s\"", filenames[i]); n = read_all(fd, buf, sizeof(buf), 0); log_info(LD_CRYPTO, "Reading entropy from \"%s\"", filenames[i]); n = read_all(fd, (char*)out, out_len, 0); close(fd); if (n != sizeof(buf)) { if (n != out_len) { log_warn(LD_CRYPTO, "Error reading from entropy source (read only %lu bytes).", (unsigned long)n); return -1; } RAND_seed(buf, (int)sizeof(buf)); memwipe(buf, 0, sizeof(buf)); seed_weak_rng(); return 0; } log_warn(LD_CRYPTO, "Cannot seed RNG -- no entropy source found."); return rand_poll_status ? 0 : -1; log_warn(LD_CRYPTO, "Cannot get strong entropy: no entropy source found."); return -1; #endif } /** Seed OpenSSL's random number generator with bytes from the operating * system. <b>startup</b> should be true iff we have just started Tor and * have not yet allocated a bunch of fds. Return 0 on success, -1 on failure. */ int crypto_seed_rng(int startup) { int rand_poll_ok = 0, load_entropy_ok = 0; uint8_t buf[ADD_ENTROPY]; /* OpenSSL has a RAND_poll function that knows about more kinds of * entropy than we do. We'll try calling that, *and* calling our own entropy * functions. If one succeeds, we'll accept the RNG as seeded. */ if (startup || RAND_POLL_IS_SAFE) { rand_poll_ok = RAND_poll(); if (rand_poll_ok == 0) log_warn(LD_CRYPTO, "RAND_poll() failed."); } load_entropy_ok = !crypto_strongest_rand(buf, sizeof(buf)); if (load_entropy_ok) { RAND_seed(buf, sizeof(buf)); } memwipe(buf, 0, sizeof(buf)); seed_weak_rng(); if (rand_poll_ok || load_entropy_ok) return 0; else return -1; } /** Write <b>n</b> bytes of strong random data to <b>to</b>. Return 0 on * success, -1 on failure. */ Loading Loading
.gitignore +6 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ .dirstamp # Stuff made by our makefiles *.bak # Python droppings *.pyc # / /Makefile Loading Loading @@ -130,6 +132,8 @@ /src/common/libor-crypto.lib /src/common/libor-event.a /src/common/libor-event.lib /src/common/libcurve25519_donna.a /src/common/libcurve25519_donna.lib # /src/config/ /src/config/Makefile Loading @@ -154,9 +158,10 @@ /src/test/bench.exe /src/test/test /src/test/test-child /src/test/test-ntor-cl /src/test/test.exe /src/test/test-child.exe /src/test/test-ntor-cl.exe # /src/tools/ /src/tools/tor-checkkey Loading
changes/ntor 0 → 100644 +40 −0 Original line number Diff line number Diff line o Major features: - Tor now supports a new circuit extension handshake designed by Ian Goldberg, Douglas Stebila, and Berkant Ustaoglu. Our original circuit extension handshake, later called "TAP", was a bit slow (especially on the server side), had a fragile security proof, and used weaker keys than we'd now prefer. The new circuit handshake uses Dan Bernstein's "curve25519" elliptic-curve Diffie-Hellman function, making it significantly more secure than the older handshake, and significantly faster. Tor can either use one of two built-in pure-C curve25519-donna implementations by Adam Langley, or link against the "nacl" library for a tuned version if present. The built-in version is very fast for 64-bit systems building with GCC. (About 10-14x faster on the server side, and about 7x faster on the client side.) The built-in 32-bit version is still faster than the old TAP protocol (about 3x), but using libnacl would be better on most 32-bit x86 hosts. Clients don't currently use this protocol by default, since comparatively few clients support it so far. To try it, set UseNTorHandshake to 1. Implements proposal 216; closes ticket #7202. - Tor servers and clients now support a better CREATE/EXTEND cell format, allowing the sender to specify multiple address, identity, and handshake types. Implements Robert Ransom's proposal 200; closes ticket #7199. o Code simplification and refactoring: - Split the onion.c file into separate modules for the onion queue and the different handshakes it supports. - Remove the marshalling/unmarshalling code for sending requests to cpuworkers over a socket, and instead just send structs. The recipient will always be the same Tor binary as the sender, so any encoding is overkill. o Testing: - Add benchmark functions to test onion handshake performance.
configure.ac +99 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ AC_ARG_ENABLE(static-zlib, AS_HELP_STRING(--enable-static-zlib, Link against a static zlib library. Requires --with-zlib-dir)) AC_ARG_ENABLE(static-tor, AS_HELP_STRING(--enable-static-tor, Create an entirely static Tor binary. Requires --with-openssl-dir and --with-libevent-dir and --with-zlib-dir)) AC_ARG_ENABLE(curve25519, AS_HELP_STRING(--disable-curve25519, Build Tor with no curve25519 elliptic-curve crypto support)) if test "$enable_static_tor" = "yes"; then enable_static_libevent="yes"; Loading Loading @@ -639,6 +641,103 @@ if test "$upnp" = "true"; then fi fi dnl ============================================================ dnl We need an implementation of curve25519. dnl set these defaults. have_a_curve25519=no build_curve25519_donna=no build_curve25519_donna_c64=no use_curve25519_donna=no use_curve25519_nacl=no CURVE25519_LIBS= if test x$enable_curve25519 != xno; then dnl The best choice is using curve25519-donna-c64, but that requires dnl that we AC_CACHE_CHECK([whether we can use curve25519-donna-c64], tor_cv_can_use_curve25519_donna_c64, [AC_RUN_IFELSE( [AC_LANG_PROGRAM([dnl #include <stdint.h> typedef unsigned uint128_t __attribute__((mode(TI))); ], [dnl uint64_t a = ((uint64_t)2000000000) * 1000000000; uint64_t b = ((uint64_t)1234567890) << 24; uint128_t c = ((uint128_t)a) * b; return ((uint64_t)(c>>96)) == 522859 && ((uint64_t)(c>>64))&0xffffffffL == 3604448702L && ((uint64_t)(c>>32))&0xffffffffL == 2351960064L && ((uint64_t)(c))&0xffffffffL == 0; ])], [tor_cv_can_use_curve25519_donna_c64=yes], [tor_cv_can_use_curve25519_donna_c64=no], [AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([dnl #include <stdint.h> typedef unsigned uint128_t __attribute__((mode(TI))); ], [dnl uint64_t a = ((uint64_t)2000000000) * 1000000000; uint64_t b = ((uint64_t)1234567890) << 24; uint128_t c = ((uint128_t)a) * b; return ((uint64_t)(c>>96)) == 522859 && ((uint64_t)(c>>64))&0xffffffffL == 3604448702L && ((uint64_t)(c>>32))&0xffffffffL == 2351960064L && ((uint64_t)(c))&0xffffffffL == 0; ])], [tor_cv_can_use_curve25519_donna_c64=cross], [tor_cv_can_use_curve25519_donna_c64=no])])]) AC_CACHE_CHECK([whether we can use curve25519 from nacl], tor_cv_can_use_curve25519_nacl, [tor_saved_LIBS="$LIBS" LIBS="$LIBS -lnacl" AC_LINK_IFELSE( [AC_LANG_PROGRAM([dnl #include <crypto_scalarmult_curve25519.h> #ifdef crypto_scalarmult_curve25519_ref_BYTES #error Hey, this is the reference implementation! #endif ], [ unsigned char *a, *b, *c; crypto_scalarmult_curve25519(a,b,c); ])], [tor_cv_can_use_curve25519_nacl=yes], [tor_cv_can_use_curve25519_nacl=no]) LIBS="$tor_saved_LIBS" ]) dnl Okay, now we need to figure out which one to actually use. Fall back dnl to curve25519-donna.c if test x$tor_cv_can_use_curve25519_donna_c64 != xno; then build_curve25519_donna_c64=yes use_curve25519_donna=yes elif test x$tor_cv_can_use_curve25519_nacl = xyes; then use_curve25519_nacl=yes CURVE25519_LIBS=-lnacl else build_curve25519_donna=yes use_curve25519_donna=yes fi have_a_curve25519=yes fi if test x$have_a_curve25519 = xyes; then AC_DEFINE(CURVE25519_ENABLED, 1, [Defined if we have a curve25519 implementation]) fi if test x$use_curve25519_donna = xyes; then AC_DEFINE(USE_CURVE25519_DONNA, 1, [Defined if we should use an internal curve25519_donna{,_c64} implementation]) fi if test x$use_curve25519_nacl = xyes; then AC_DEFINE(USE_CURVE25519_NACL, 1, [Defined if we should use a curve25519 from nacl]) fi AM_CONDITIONAL(BUILD_CURVE25519_DONNA, test x$build_curve25519_donna = xyes) AM_CONDITIONAL(BUILD_CURVE25519_DONNA_C64, test x$build_curve25519_donna_c64 = xyes) AM_CONDITIONAL(CURVE25519_ENABLED, test x$have_a_curve25519 = xyes) AC_SUBST(CURVE25519_LIBS) dnl Make sure to enable support for large off_t if available. AC_SYS_LARGEFILE Loading
doc/tor.1.txt +10 −0 Original line number Diff line number Diff line Loading @@ -1218,6 +1218,16 @@ The following options are useful only for clients (that is, if "auto" (recommended) then it is on for all clients that do not set FetchUselessDescriptors. (Default: auto) **UseNTorHandshake** **0**|**1**|**auto**:: The "ntor" circuit-creation handshake is faster and (we think) more secure than the original ("TAP") circuit handshake, but starting to use it too early might make your client stand out. If this option is 0, your Tor client won't use the ntor handshake. If it's 1, your Tor client will use the ntor handshake to extend circuits through servers that support it. If this option is "auto" (recommended), then your client will use the ntor handshake once enough directory authorities recommend it. (Default: auto) **PathBiasCircThreshold** __NUM__ + **PathBiasNoticeRate** __NUM__ + Loading
src/common/crypto.c +124 −39 Original line number Diff line number Diff line Loading @@ -2036,6 +2036,16 @@ crypto_dh_new(int dh_type) return NULL; } /** Return a copy of <b>dh</b>, sharing its internal state. */ crypto_dh_t * crypto_dh_dup(const crypto_dh_t *dh) { crypto_dh_t *dh_new = tor_malloc_zero(sizeof(crypto_dh_t)); dh_new->dh = dh->dh; DH_up_ref(dh->dh); return dh_new; } /** Return the length of the DH key in <b>dh</b>, in bytes. */ int Loading Loading @@ -2174,8 +2184,8 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh, goto error; } secret_len = result; if (crypto_expand_key_material(secret_tmp, secret_len, secret_out, secret_bytes_out)<0) if (crypto_expand_key_material_TAP((uint8_t*)secret_tmp, secret_len, (uint8_t*)secret_out, secret_bytes_out)<0) goto error; secret_len = secret_bytes_out; Loading @@ -2201,15 +2211,18 @@ crypto_dh_compute_secret(int severity, crypto_dh_t *dh, * <b>key_out</b> by taking the first <b>key_out_len</b> bytes of * H(K | [00]) | H(K | [01]) | .... * * This is the key expansion algorithm used in the "TAP" circuit extension * mechanism; it shouldn't be used for new protocols. * * Return 0 on success, -1 on failure. */ int crypto_expand_key_material(const char *key_in, size_t key_in_len, char *key_out, size_t key_out_len) crypto_expand_key_material_TAP(const uint8_t *key_in, size_t key_in_len, uint8_t *key_out, size_t key_out_len) { int i; char *cp, *tmp = tor_malloc(key_in_len+1); char digest[DIGEST_LEN]; uint8_t *cp, *tmp = tor_malloc(key_in_len+1); uint8_t digest[DIGEST_LEN]; /* If we try to get more than this amount of key data, we'll repeat blocks.*/ tor_assert(key_out_len <= DIGEST_LEN*256); Loading @@ -2218,7 +2231,7 @@ crypto_expand_key_material(const char *key_in, size_t key_in_len, for (cp = key_out, i=0; cp < key_out+key_out_len; ++i, cp += DIGEST_LEN) { tmp[key_in_len] = i; if (crypto_digest(digest, tmp, key_in_len+1)) if (crypto_digest((char*)digest, (const char *)tmp, key_in_len+1)) goto err; memcpy(cp, digest, MIN(DIGEST_LEN, key_out_len-(cp-key_out))); } Loading @@ -2234,6 +2247,65 @@ crypto_expand_key_material(const char *key_in, size_t key_in_len, return -1; } /** Expand some secret key material according to RFC5869, using SHA256 as the * underlying hash. The <b>key_in_len</b> bytes at <b>key_in</b> are the * secret key material; the <b>salt_in_len</b> bytes at <b>salt_in</b> and the * <b>info_in_len</b> bytes in <b>info_in_len</b> are the algorithm's "salt" * and "info" parameters respectively. On success, write <b>key_out_len</b> * bytes to <b>key_out</b> and return 0. On failure, return -1. */ int crypto_expand_key_material_rfc5869_sha256( const uint8_t *key_in, size_t key_in_len, const uint8_t *salt_in, size_t salt_in_len, const uint8_t *info_in, size_t info_in_len, uint8_t *key_out, size_t key_out_len) { uint8_t prk[DIGEST256_LEN]; uint8_t tmp[DIGEST256_LEN + 128 + 1]; uint8_t mac[DIGEST256_LEN]; int i; uint8_t *outp; size_t tmp_len; crypto_hmac_sha256((char*)prk, (const char*)salt_in, salt_in_len, (const char*)key_in, key_in_len); /* If we try to get more than this amount of key data, we'll repeat blocks.*/ tor_assert(key_out_len <= DIGEST256_LEN * 256); tor_assert(info_in_len <= 128); memset(tmp, 0, sizeof(tmp)); outp = key_out; i = 1; while (key_out_len) { size_t n; if (i > 1) { memcpy(tmp, mac, DIGEST256_LEN); memcpy(tmp+DIGEST256_LEN, info_in, info_in_len); tmp[DIGEST256_LEN+info_in_len] = i; tmp_len = DIGEST256_LEN + info_in_len + 1; } else { memcpy(tmp, info_in, info_in_len); tmp[info_in_len] = i; tmp_len = info_in_len + 1; } crypto_hmac_sha256((char*)mac, (const char*)prk, DIGEST256_LEN, (const char*)tmp, tmp_len); n = key_out_len < DIGEST256_LEN ? key_out_len : DIGEST256_LEN; memcpy(outp, mac, n); key_out_len -= n; outp += n; ++i; } memwipe(tmp, 0, sizeof(tmp)); memwipe(mac, 0, sizeof(mac)); return 0; } /** Free a DH key exchange object. */ void Loading Loading @@ -2272,22 +2344,16 @@ seed_weak_rng(void) tor_init_weak_random(seed); } /** Seed OpenSSL's random number generator with bytes from the operating * system. <b>startup</b> should be true iff we have just started Tor and * have not yet allocated a bunch of fds. Return 0 on success, -1 on failure. /** Try to get <b>out_len</b> bytes of the strongest entropy we can generate, * storing it into <b>out</b>. */ int crypto_seed_rng(int startup) crypto_strongest_rand(uint8_t *out, size_t out_len) { int rand_poll_status = 0; /* local variables */ #ifdef _WIN32 unsigned char buf[ADD_ENTROPY]; static int provider_set = 0; static HCRYPTPROV provider; #else char buf[ADD_ENTROPY]; static const char *filenames[] = { "/dev/srandom", "/dev/urandom", "/dev/random", NULL }; Loading @@ -2295,58 +2361,77 @@ crypto_seed_rng(int startup) size_t n; #endif /* OpenSSL has a RAND_poll function that knows about more kinds of * entropy than we do. We'll try calling that, *and* calling our own entropy * functions. If one succeeds, we'll accept the RNG as seeded. */ if (startup || RAND_POLL_IS_SAFE) { rand_poll_status = RAND_poll(); if (rand_poll_status == 0) log_warn(LD_CRYPTO, "RAND_poll() failed."); } #ifdef _WIN32 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 rand_poll_status ? 0 : -1; return -1; } } provider_set = 1; } if (!CryptGenRandom(provider, sizeof(buf), buf)) { if (!CryptGenRandom(provider, out_len, out)) { log_warn(LD_CRYPTO, "Can't get entropy from CryptoAPI."); return rand_poll_status ? 0 : -1; return -1; } RAND_seed(buf, sizeof(buf)); memwipe(buf, 0, sizeof(buf)); seed_weak_rng(); return 0; #else for (i = 0; filenames[i]; ++i) { fd = open(filenames[i], O_RDONLY, 0); if (fd<0) continue; log_info(LD_CRYPTO, "Seeding RNG from \"%s\"", filenames[i]); n = read_all(fd, buf, sizeof(buf), 0); log_info(LD_CRYPTO, "Reading entropy from \"%s\"", filenames[i]); n = read_all(fd, (char*)out, out_len, 0); close(fd); if (n != sizeof(buf)) { if (n != out_len) { log_warn(LD_CRYPTO, "Error reading from entropy source (read only %lu bytes).", (unsigned long)n); return -1; } RAND_seed(buf, (int)sizeof(buf)); memwipe(buf, 0, sizeof(buf)); seed_weak_rng(); return 0; } log_warn(LD_CRYPTO, "Cannot seed RNG -- no entropy source found."); return rand_poll_status ? 0 : -1; log_warn(LD_CRYPTO, "Cannot get strong entropy: no entropy source found."); return -1; #endif } /** Seed OpenSSL's random number generator with bytes from the operating * system. <b>startup</b> should be true iff we have just started Tor and * have not yet allocated a bunch of fds. Return 0 on success, -1 on failure. */ int crypto_seed_rng(int startup) { int rand_poll_ok = 0, load_entropy_ok = 0; uint8_t buf[ADD_ENTROPY]; /* OpenSSL has a RAND_poll function that knows about more kinds of * entropy than we do. We'll try calling that, *and* calling our own entropy * functions. If one succeeds, we'll accept the RNG as seeded. */ if (startup || RAND_POLL_IS_SAFE) { rand_poll_ok = RAND_poll(); if (rand_poll_ok == 0) log_warn(LD_CRYPTO, "RAND_poll() failed."); } load_entropy_ok = !crypto_strongest_rand(buf, sizeof(buf)); if (load_entropy_ok) { RAND_seed(buf, sizeof(buf)); } memwipe(buf, 0, sizeof(buf)); seed_weak_rng(); if (rand_poll_ok || load_entropy_ok) return 0; else return -1; } /** Write <b>n</b> bytes of strong random data to <b>to</b>. Return 0 on * success, -1 on failure. */ Loading