commit 1b52e95028e0d84b7a112e4b8f2e393261dbb19c
Merge: 0989ba3 5eb584e
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu May 28 11:04:33 2015 -0400
Merge branch '12498_ed25519_keys_v6'
Fixed numerous conflicts, and ported code to use new base64 api.
doc/tor.1.txt | 24 +
scripts/codegen/makedesc.py | 355 ++++---
scripts/codegen/run_trunnel.sh | 4 +-
src/common/container.c | 13 +
src/common/container.h | 1 +
src/common/crypto.c | 102 +-
src/common/crypto.h | 20 +-
src/common/crypto_ed25519.c | 21 +
src/common/crypto_ed25519.h | 19 +-
src/common/crypto_format.c | 39 +
src/common/tortls.c | 76 +-
src/common/tortls.h | 29 +-
src/or/channel.c | 8 +-
src/or/channel.h | 5 +-
src/or/channeltls.c | 161 ++-
src/or/channeltls.h | 10 +
src/or/config.c | 20 +
src/or/config.h | 4 +
src/or/connection_or.c | 180 ++--
src/or/connection_or.h | 12 +-
src/or/dircollate.c | 257 +++++
src/or/dircollate.h | 49 +
src/or/dirserv.c | 79 ++
src/or/dirvote.c | 87 +-
src/or/dirvote.h | 9 +-
src/or/include.am | 20 +-
src/or/keypin.c | 419 ++++++++
src/or/keypin.h | 46 +
src/or/main.c | 38 +-
src/or/microdesc.c | 1 +
src/or/or.h | 41 +-
src/or/router.c | 242 ++++-
src/or/router.h | 8 +-
src/or/routerkeys.c | 648 +++++++++++++
src/or/routerkeys.h | 67 ++
src/or/routerlist.c | 27 +-
src/or/routerlist.h | 7 +-
src/or/routerparse.c | 310 +++++-
src/or/routerparse.h | 4 +-
src/or/torcert.c | 280 ++++++
src/or/torcert.h | 76 ++
src/test/example_extrainfo.inc | 233 +++++
src/test/failing_routerdescs.inc | 901 +++++++++++++++++
src/test/include.am | 6 +-
src/test/test.c | 4 +
src/test/test_containers.c | 38 +
src/test/test_crypto.c | 20 +-
src/test/test_dir.c | 133 ++-
src/test/test_keypin.c | 255 +++++
src/test/test_link_handshake.c | 914 +++++++++++++++++
src/test/test_microdesc.c | 93 ++
src/test/test_routerkeys.c | 540 ++++++++++-
src/trunnel/ed25519_cert.c | 887 +++++++++++++++++
src/trunnel/ed25519_cert.h | 288 ++++++
src/trunnel/ed25519_cert.trunnel | 76 ++
src/trunnel/include.am | 21 +-
src/trunnel/link_handshake.c | 1885 ++++++++++++++++++++++++++++++++++++
src/trunnel/link_handshake.h | 654 +++++++++++++
src/trunnel/link_handshake.trunnel | 57 ++
59 files changed, 10365 insertions(+), 458 deletions(-)
diff --cc src/common/crypto.c
index fcd862f,2ccff80..d77d5e2
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@@ -2588,93 -2711,76 +2607,152 @@@ base64_encode(char *dest, size_t destle
return -1;
if (destlen > SIZE_T_CEILING)
return -1;
- if (destlen)
- *dest = 0; /* Ensure we always initialize the buffer */
-
- EVP_EncodeInit(&ctx);
- EVP_EncodeUpdate(&ctx, (unsigned char*)dest, &len,
- (unsigned char*)src, (int)srclen);
- EVP_EncodeFinal(&ctx, (unsigned char*)(dest+len), &ret);
- ret += len;
- return ret;
+ if (enclen > INT_MAX)
+ return -1;
+
+ memset(dest, 0, enclen);
+
+ /* XXX/Yawning: If this ends up being too slow, this can be sped up
+ * by separating the multiline format case and the normal case, and
+ * processing 48 bytes of input at a time when newlines are desired.
+ */
+#define ENCODE_CHAR(ch) \
+ STMT_BEGIN \
+ *d++ = ch; \
+ if (flags & BASE64_ENCODE_MULTILINE) { \
+ if (++linelen % BASE64_OPENSSL_LINELEN == 0) { \
+ linelen = 0; \
+ *d++ = '\n'; \
+ } \
+ } \
+ STMT_END
+
+#define ENCODE_N(idx) \
+ ENCODE_CHAR(base64_encode_table[(n >> ((3 - idx) * 6)) & 0x3f])
+
+#define ENCODE_PAD() ENCODE_CHAR('=')
+
+ /* Iterate over all the bytes in src. Each one will add 8 bits to the
+ * value we're encoding. Accumulate bits in <b>n</b>, and whenever we
+ * have 24 bits, batch them into 4 bytes and flush those bytes to dest.
+ */
+ for ( ; usrc < eous; ++usrc) {
+ n = (n << 8) | *usrc;
+ if ((++n_idx) == 3) {
+ ENCODE_N(0);
+ ENCODE_N(1);
+ ENCODE_N(2);
+ ENCODE_N(3);
+ n_idx = 0;
+ n = 0;
+ }
+ }
+ switch (n_idx) {
+ case 0:
+ /* 0 leftover bits, no pading to add. */
+ break;
+ case 1:
+ /* 8 leftover bits, pad to 12 bits, write the 2 6-bit values followed
+ * by 2 padding characters.
+ */
+ n <<= 4;
+ ENCODE_N(2);
+ ENCODE_N(3);
+ ENCODE_PAD();
+ ENCODE_PAD();
+ break;
+ case 2:
+ /* 16 leftover bits, pad to 18 bits, write the 3 6-bit values followed
+ * by 1 padding character.
+ */
+ n <<= 2;
+ ENCODE_N(1);
+ ENCODE_N(2);
+ ENCODE_N(3);
+ ENCODE_PAD();
+ break;
+ default:
+ /* Something went catastrophically wrong. */
+ tor_fragile_assert();
+ return -1;
+ }
+
+#undef ENCODE_N
+#undef ENCODE_PAD
+#undef ENCODE_CHAR
+
+ /* Multiline output always includes at least one newline. */
+ if (flags & BASE64_ENCODE_MULTILINE && linelen != 0)
+ *d++ = '\n';
+
+ tor_assert(d - dest == (ptrdiff_t)enclen);
+
+ *d++ = '\0'; /* NUL terminate the output. */
+
+ return (int) enclen;
}
+ /** As base64_encode, but do not add any internal spaces or external padding
+ * to the output stream. */
+ int
+ base64_encode_nopad(char *dest, size_t destlen,
+ const uint8_t *src, size_t srclen)
+ {
- int n = base64_encode(dest, destlen, (const char*) src, srclen);
++ int n = base64_encode(dest, destlen, (const char*) src, srclen, 0);
+ if (n <= 0)
+ return n;
+ tor_assert((size_t)n < destlen && dest[n] == 0);
+ char *in, *out;
+ in = out = dest;
+ while (*in) {
+ if (*in == '=' || *in == '\n') {
+ ++in;
+ } else {
+ *out++ = *in++;
+ }
+ }
+ *out = 0;
+
+ tor_assert(out - dest <= INT_MAX);
+
+ return (int)(out - dest);
+ }
+
+ /** As base64_decode, but do not require any padding on the input */
+ int
+ base64_decode_nopad(uint8_t *dest, size_t destlen,
+ const char *src, size_t srclen)
+ {
+ if (srclen > SIZE_T_CEILING - 4)
+ return -1;
+ char *buf = tor_malloc(srclen + 4);
+ memcpy(buf, src, srclen+1);
+ size_t buflen;
+ switch (srclen % 4)
+ {
+ case 0:
+ default:
+ buflen = srclen;
+ break;
+ case 1:
+ tor_free(buf);
+ return -1;
+ case 2:
+ memcpy(buf+srclen, "==", 3);
+ buflen = srclen + 2;
+ break;
+ case 3:
+ memcpy(buf+srclen, "=", 2);
+ buflen = srclen + 1;
+ break;
+ }
+ int n = base64_decode((char*)dest, destlen, buf, buflen);
+ tor_free(buf);
+ return n;
+ }
+
+#undef BASE64_OPENSSL_LINELEN
+
/** @{ */
/** Special values used for the base64_decode_table */
#define X 255
@@@ -2795,8 -2922,9 +2873,9 @@@ base64_decode(char *dest, size_t destle
#undef PAD
/** Base64 encode DIGEST_LINE bytes from <b>digest</b>, remove the trailing =
- * and newline characters, and store the nul-terminated result in the first
+ * characters, and store the nul-terminated result in the first
* BASE64_DIGEST_LEN+1 bytes of <b>d64</b>. */
+ /* XXXX unify with crypto_format.c code */
int
digest_to_base64(char *d64, const char *digest)
{
@@@ -2820,8 -2961,10 +2900,9 @@@ digest_from_base64(char *digest, const
}
/** Base64 encode DIGEST256_LINE bytes from <b>digest</b>, remove the
- * trailing = and newline characters, and store the nul-terminated result in
- * the first BASE64_DIGEST256_LEN+1 bytes of <b>d64</b>. */
-/* XXXX unify with crypto_format.c code */
+ * trailing = characters, and store the nul-terminated result in the first
- * BASE64_DIGEST256_LEN+1 bytes of <b>d64</b>. */
++ * BASE64_DIGEST256_LEN+1 bytes of <b>d64</b>. */
++ /* XXXX unify with crypto_format.c code */
int
digest256_to_base64(char *d64, const char *digest)
{
diff --cc src/common/crypto.h
index 05572f4,15d1f6e..b953ab9
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@@ -273,11 -273,13 +278,16 @@@ struct smartlist_t
void *smartlist_choose(const struct smartlist_t *sl);
void smartlist_shuffle(struct smartlist_t *sl);
-int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen);
+#define BASE64_ENCODE_MULTILINE 1
+size_t base64_encode_size(size_t srclen, int flags);
+int base64_encode(char *dest, size_t destlen, const char *src, size_t srclen,
+ int flags);
int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen);
+ int base64_encode_nopad(char *dest, size_t destlen,
+ const uint8_t *src, size_t srclen);
+ int base64_decode_nopad(uint8_t *dest, size_t destlen,
+ const char *src, size_t srclen);
+
/** Characters that can appear (case-insensitively) in a base32 encoding. */
#define BASE32_CHARS "abcdefghijklmnopqrstuvwxyz234567"
void base32_encode(char *dest, size_t destlen, const char *src, size_t srclen);
diff --cc src/common/tortls.c
index 2b8daaa,e498b2a..098df9d
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@@ -116,8 -114,15 +116,8 @@@
#define SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x0010
#endif
-/** Does the run-time openssl version look like we need
- * SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */
-static int use_unsafe_renegotiation_op = 0;
-/** Does the run-time openssl version look like we need
- * SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */
-static int use_unsafe_renegotiation_flag = 0;
-
/** Structure that we use for a single certificate. */
- struct tor_cert_t {
+ struct tor_x509_cert_t {
X509 *cert;
uint8_t *encoded;
size_t encoded_len;
diff --cc src/or/channeltls.c
index 1cf697c,0376e74..ecf0218
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@@ -22,8 -24,8 +24,9 @@@
#include "connection.h"
#include "connection_or.h"
#include "control.h"
+ #include "link_handshake.h"
#include "relay.h"
+#include "rephist.h"
#include "router.h"
#include "routerlist.h"
#include "scheduler.h"
diff --cc src/or/include.am
index 0ce3cdc,9245ade..6bbf788
--- a/src/or/include.am
+++ b/src/or/include.am
@@@ -77,18 -80,19 +80,14 @@@ LIBTOR_A_SOURCES =
src/or/scheduler.c \
src/or/statefile.c \
src/or/status.c \
+ src/or/torcert.c \
src/or/onion_ntor.c \
$(evdns_source) \
- $(tor_platform_source) \
- src/or/config_codedigest.c
+ $(tor_platform_source)
src_or_libtor_a_SOURCES = $(LIBTOR_A_SOURCES)
src_or_libtor_testing_a_SOURCES = $(LIBTOR_A_SOURCES)
- #libtor_a_LIBADD = $(top_builddir)/common/libor.a \
- # $(top_builddir)/common/libor-crypto.a \
- # $(top_builddir)/common/libor-event.a
-
-
-#libtor_a_LIBADD = ../common/libor.a ../common/libor-crypto.a \
-# ../common/libor-event.a
-#src_or_libtor_a_LIBADD = src/trunnel/libor-trunnel.a
-
src_or_tor_SOURCES = src/or/tor_main.c
AM_CPPFLAGS += -I$(srcdir)/src/or -Isrc/or
@@@ -120,12 -124,12 +119,12 @@@ src_or_tor_cov_CFLAGS = $(AM_CFLAGS) $(
src_or_tor_cov_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
src_or_tor_cov_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@ @TOR_SYSTEMD_LIBS@
-TESTING_TOR_BINARY = ./src/or/tor-cov
+TESTING_TOR_BINARY = $(top_builddir)/src/or/tor-cov
else
-TESTING_TOR_BINARY = ./src/or/tor
+TESTING_TOR_BINARY = $(top_builddir)/src/or/tor
endif
ORHEADERS = \
diff --cc src/or/main.c
index 74e6b33,4fac17a..bbee8e0
--- a/src/or/main.c
+++ b/src/or/main.c
@@@ -1200,46 -1205,7 +1202,49 @@@ get_signewnym_epoch(void
return newnym_epoch;
}
-static time_t time_to_check_descriptor = 0;
+typedef struct {
+ time_t last_rotated_x509_certificate;
+ time_t check_v3_certificate;
+ time_t check_listeners;
+ time_t download_networkstatus;
+ time_t try_getting_descriptors;
+ time_t reset_descriptor_failures;
+ time_t add_entropy;
+ time_t write_bridge_status_file;
+ time_t downrate_stability;
+ time_t save_stability;
+ time_t clean_caches;
+ time_t recheck_bandwidth;
+ time_t check_for_expired_networkstatus;
+ time_t write_stats_files;
+ time_t write_bridge_stats;
+ time_t check_port_forwarding;
+ time_t launch_reachability_tests;
+ time_t retry_dns_init;
+ time_t next_heartbeat;
+ time_t check_descriptor;
+ /** When do we next launch DNS wildcarding checks? */
+ time_t check_for_correct_dns;
++ /** When do we next make sure our Ed25519 keys aren't about to expire? */
++ time_t check_ed_keys;
++
+} time_to_t;
+
+static time_to_t time_to = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/** Reset all the time_to's so we'll do all our actions again as if we
+ * just started up.
+ * Useful if our clock just moved back a long time from the future,
+ * so we don't wait until that future arrives again before acting.
+ */
+void
+reset_all_main_loop_timers(void)
+{
+ memset(&time_to, 0, sizeof(time_to));
+}
+
/**
* Update our schedule so that we'll check whether we need to update our
* descriptor immediately, rather than after up to CHECK_DESCRIPTOR_INTERVAL
@@@ -1297,8 -1282,20 +1302,20 @@@ run_scheduled_events(time_t now
router_upload_dir_desc_to_dirservers(0);
}
- if (is_server && time_to_check_ed_keys < now) {
++ if (is_server && time_to.check_ed_keys < now) {
+ if (should_make_new_ed_keys(options, now)) {
+ if (load_ed_keys(options, now) < 0 ||
+ generate_ed_link_cert(options, now)) {
+ log_err(LD_OR, "Unable to update Ed25519 keys! Exiting.");
+ tor_cleanup();
+ exit(0);
+ }
+ }
- time_to_check_ed_keys = now + 30;
++ time_to.check_ed_keys = now + 30;
+ }
+
if (!should_delay_dir_fetches(options, NULL) &&
- time_to_try_getting_descriptors < now) {
+ time_to.try_getting_descriptors < now) {
update_all_descriptor_downloads(now);
update_extrainfo_downloads(now);
if (router_have_minimum_dir_info())
diff --cc src/or/router.c
index 24b7c75,00cd057..6532f97
--- a/src/or/router.c
+++ b/src/or/router.c
@@@ -2358,6 -2372,21 +2403,22 @@@ router_dump_router_to_string(routerinfo
goto err;
}
+ if (emit_ed_sigs) {
+ /* Encode ed25519 signing cert */
+ char ed_cert_base64[256];
+ if (base64_encode(ed_cert_base64, sizeof(ed_cert_base64),
+ (const char*)router->signing_key_cert->encoded,
- router->signing_key_cert->encoded_len) < 0) {
++ router->signing_key_cert->encoded_len,
++ BASE64_ENCODE_MULTILINE) < 0) {
+ log_err(LD_BUG,"Couldn't base64-encode signing key certificate!");
+ goto err;
+ }
+ tor_asprintf(&ed_cert_line, "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "%s"
+ "-----END ED25519 CERT-----\n", ed_cert_base64);
+ }
+
/* PEM-encode the onion key */
if (crypto_pk_write_public_key_to_string(router->onion_pkey,
&onion_pkey,&onion_pkeylen)<0) {
@@@ -2372,6 -2401,67 +2433,69 @@@
goto err;
}
+ /* Cross-certify with RSA key */
+ if (tap_key && router->signing_key_cert &&
+ router->signing_key_cert->signing_key_included) {
+ char buf[256];
+ int tap_cc_len = 0;
+ uint8_t *tap_cc =
+ make_tap_onion_key_crosscert(tap_key,
+ &router->signing_key_cert->signing_key,
+ router->identity_pkey,
+ &tap_cc_len);
+ if (!tap_cc) {
+ log_warn(LD_BUG,"make_tap_onion_key_crosscert failed!");
+ goto err;
+ }
+
- if (base64_encode(buf, sizeof(buf), (const char*)tap_cc, tap_cc_len) < 0) {
++ if (base64_encode(buf, sizeof(buf), (const char*)tap_cc, tap_cc_len,
++ BASE64_ENCODE_MULTILINE) < 0) {
+ log_warn(LD_BUG,"base64_encode(rsa_crosscert) failed!");
+ tor_free(tap_cc);
+ goto err;
+ }
+ tor_free(tap_cc);
+
+ tor_asprintf(&rsa_tap_cc_line,
+ "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n"
+ "%s"
+ "-----END CROSSCERT-----\n", buf);
+ }
+
+ /* Cross-certify with onion keys */
+ if (ntor_keypair && router->signing_key_cert &&
+ router->signing_key_cert->signing_key_included) {
+ int sign = 0;
+ char buf[256];
+ /* XXXX Base the expiration date on the actual onion key expiration time?*/
+ tor_cert_t *cert =
+ make_ntor_onion_key_crosscert(ntor_keypair,
+ &router->signing_key_cert->signing_key,
+ router->cache_info.published_on,
+ MIN_ONION_KEY_LIFETIME, &sign);
+ if (!cert) {
+ log_warn(LD_BUG,"make_ntor_onion_key_crosscert failed!");
+ goto err;
+ }
+ tor_assert(sign == 0 || sign == 1);
+
+ if (base64_encode(buf, sizeof(buf),
- (const char*)cert->encoded, cert->encoded_len)<0) {
++ (const char*)cert->encoded, cert->encoded_len,
++ BASE64_ENCODE_MULTILINE)<0) {
+ log_warn(LD_BUG,"base64_encode(ntor_crosscert) failed!");
+ tor_cert_free(cert);
+ goto err;
+ }
+ tor_cert_free(cert);
+
+ tor_asprintf(&ntor_cc_line,
+ "ntor-onion-key-crosscert %d\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "%s"
+ "-----END ED25519 CERT-----\n", sign, buf);
+ }
+
/* Encode the publication time. */
format_iso_time(published, router->cache_info.published_on);
@@@ -2695,9 -2819,33 +2853,34 @@@ extrainfo_dump_to_string(char **s_out,
extrainfo->cache_info.identity_digest, DIGEST_LEN);
format_iso_time(published, extrainfo->cache_info.published_on);
bandwidth_usage = rep_hist_get_bandwidth_lines();
+ if (emit_ed_sigs) {
+ if (!extrainfo->signing_key_cert->signing_key_included ||
+ !ed25519_pubkey_eq(&extrainfo->signing_key_cert->signed_key,
+ &signing_keypair->pubkey)) {
+ log_warn(LD_BUG, "Tried to sign a extrainfo descriptor with a "
+ "mismatched ed25519 key chain %d",
+ extrainfo->signing_key_cert->signing_key_included);
+ goto err;
+ }
+ char ed_cert_base64[256];
+ if (base64_encode(ed_cert_base64, sizeof(ed_cert_base64),
+ (const char*)extrainfo->signing_key_cert->encoded,
- extrainfo->signing_key_cert->encoded_len) < 0) {
++ extrainfo->signing_key_cert->encoded_len,
++ BASE64_ENCODE_MULTILINE) < 0) {
+ log_err(LD_BUG,"Couldn't base64-encode signing key certificate!");
+ goto err;
+ }
+ tor_asprintf(&ed_cert_line, "identity-ed25519\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "%s"
+ "-----END ED25519 CERT-----\n", ed_cert_base64);
+ } else {
+ ed_cert_line = tor_strdup("");
+ }
- tor_asprintf(&pre, "extra-info %s %s\npublished %s\n%s",
+ tor_asprintf(&pre, "extra-info %s %s\n%spublished %s\n%s",
extrainfo->nickname, identity,
+ ed_cert_line,
published, bandwidth_usage);
tor_free(bandwidth_usage);
smartlist_add(chunks, pre);
diff --cc src/or/router.h
index 73b43bc,695cfd3..61b35d6
--- a/src/or/router.h
+++ b/src/or/router.h
@@@ -89,10 -89,12 +89,13 @@@ const uint8_t *router_get_my_id_digest(
int router_extrainfo_digest_is_me(const char *digest);
int router_is_me(const routerinfo_t *router);
int router_pick_published_address(const or_options_t *options, uint32_t *addr);
+int router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e);
int router_rebuild_descriptor(int force);
char *router_dump_router_to_string(routerinfo_t *router,
- crypto_pk_t *ident_key);
+ const crypto_pk_t *ident_key,
+ const crypto_pk_t *tap_key,
+ const curve25519_keypair_t *ntor_keypair,
+ const ed25519_keypair_t *signing_keypair);
char *router_dump_exit_policy_to_string(const routerinfo_t *router,
int include_ipv4,
int include_ipv6);
diff --cc src/or/routerlist.c
index fd09679,a531051..7eba13a
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@@ -37,7 -38,8 +38,9 @@@
#include "routerlist.h"
#include "routerparse.h"
#include "routerset.h"
-#include "../common/sandbox.h"
+#include "sandbox.h"
+ #include "torcert.h"
++
// #define DEBUG_ROUTERLIST
/****************************************************************************/
diff --cc src/test/test_crypto.c
index 7944864,15ba14b..6cba850
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@@ -696,8 -618,9 +696,9 @@@ test_crypto_formats(void *arg
/* Base64 tests */
memset(data1, 6, 1024);
for (idx = 0; idx < 10; ++idx) {
- i = base64_encode(data2, 1024, data1, idx);
+ i = base64_encode(data2, 1024, data1, idx, 0);
tt_int_op(i, OP_GE, 0);
+ tt_int_op(i, OP_EQ, strlen(data2));
j = base64_decode(data3, 1024, data2, i);
tt_int_op(j,OP_EQ, idx);
tt_mem_op(data3,OP_EQ, data1, idx);
diff --cc src/test/test_dir.c
index a949f5d,5f68c34..3e9e955
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@@ -127,6 -133,22 +133,23 @@@ test_dir_formats(void *arg
ex2->prt_min = ex2->prt_max = 24;
r2 = tor_malloc_zero(sizeof(routerinfo_t));
r2->addr = 0x0a030201u; /* 10.3.2.1 */
+ ed25519_keypair_t kp1, kp2;
+ ed25519_secret_key_from_seed(&kp1.seckey,
+ (const uint8_t*)"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY");
+ ed25519_public_key_generate(&kp1.pubkey, &kp1.seckey);
+ ed25519_secret_key_from_seed(&kp2.seckey,
+ (const uint8_t*)"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
+ ed25519_public_key_generate(&kp2.pubkey, &kp2.seckey);
+ r2->signing_key_cert = tor_cert_create(&kp1,
+ CERT_TYPE_ID_SIGNING,
+ &kp2.pubkey,
+ now, 86400,
+ CERT_FLAG_INCLUDE_SIGNING_KEY);
+ char cert_buf[256];
+ base64_encode(cert_buf, sizeof(cert_buf),
+ (const char*)r2->signing_key_cert->encoded,
- r2->signing_key_cert->encoded_len);
++ r2->signing_key_cert->encoded_len,
++ BASE64_ENCODE_MULTILINE);
r2->platform = tor_strdup(platform);
r2->cache_info.published_on = 5;
r2->or_port = 9005;
@@@ -215,19 -243,49 +244,52 @@@
strlcat(buf2, pk2_str, sizeof(buf2));
strlcat(buf2, "signing-key\n", sizeof(buf2));
strlcat(buf2, pk1_str, sizeof(buf2));
+ int rsa_cc_len;
+ rsa_cc = make_tap_onion_key_crosscert(pk2,
+ &kp1.pubkey,
+ pk1,
+ &rsa_cc_len);
+ tt_assert(rsa_cc);
- base64_encode(cert_buf, sizeof(cert_buf), (char*)rsa_cc, rsa_cc_len);
++ base64_encode(cert_buf, sizeof(cert_buf), (char*)rsa_cc, rsa_cc_len,
++ BASE64_ENCODE_MULTILINE);
+ strlcat(buf2, "onion-key-crosscert\n"
+ "-----BEGIN CROSSCERT-----\n", sizeof(buf2));
+ strlcat(buf2, cert_buf, sizeof(buf2));
+ strlcat(buf2, "-----END CROSSCERT-----\n", sizeof(buf2));
+ int ntor_cc_sign;
+ ntor_cc = make_ntor_onion_key_crosscert(&r2_onion_keypair,
+ &kp1.pubkey,
+ r2->cache_info.published_on,
+ MIN_ONION_KEY_LIFETIME,
+ &ntor_cc_sign);
+ tt_assert(ntor_cc);
+ base64_encode(cert_buf, sizeof(cert_buf),
- (char*)ntor_cc->encoded, ntor_cc->encoded_len);
++ (char*)ntor_cc->encoded, ntor_cc->encoded_len,
++ BASE64_ENCODE_MULTILINE);
+ tor_snprintf(buf2+strlen(buf2), sizeof(buf2)-strlen(buf2),
+ "ntor-onion-key-crosscert %d\n"
+ "-----BEGIN ED25519 CERT-----\n"
+ "%s"
+ "-----END ED25519 CERT-----\n", ntor_cc_sign, cert_buf);
+
strlcat(buf2, "hidden-service-dir\n", sizeof(buf2));
- strlcat(buf2, "ntor-onion-key "
- "skyinAnvardNostarsNomoonNowindormistsorsnow=\n", sizeof(buf2));
+ strlcat(buf2, "ntor-onion-key ", sizeof(buf2));
+ base64_encode(cert_buf, sizeof(cert_buf),
- (const char*)r2_onion_keypair.pubkey.public_key, 32);
++ (const char*)r2_onion_keypair.pubkey.public_key, 32,
++ BASE64_ENCODE_MULTILINE);
+ strlcat(buf2, cert_buf, sizeof(buf2));
strlcat(buf2, "accept *:80\nreject 18.0.0.0/8:24\n", sizeof(buf2));
- strlcat(buf2, "router-signature\n", sizeof(buf2));
+ strlcat(buf2, "router-sig-ed25519 ", sizeof(buf2));
- buf = router_dump_router_to_string(r2, pk1);
+ buf = router_dump_router_to_string(r2, pk1, pk2, &r2_onion_keypair, &kp2);
+ tt_assert(buf);
buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same
* twice */
- tt_str_op(buf,OP_EQ, buf2);
+
+ tt_str_op(buf, OP_EQ, buf2);
tor_free(buf);
- buf = router_dump_router_to_string(r2, pk1);
+ buf = router_dump_router_to_string(r2, pk1, NULL, NULL, NULL);
cp = buf;
rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL);
tt_assert(rp2);