commit 4575a9637b902dbf835e96b5d245a6d53f33a868
Author: Zack Weinberg <zackw(a)cmu.edu>
Date: Wed Jun 20 22:49:56 2012 -0700
Add another testing option to turn off all encryption in the chopper.
---
src/crypt.cc | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/crypt.h | 20 +++++++++++
src/protocol/chop.cc | 68 +++++++++++++++++++++++++------------
3 files changed, 157 insertions(+), 22 deletions(-)
diff --git a/src/crypt.cc b/src/crypt.cc
index 1110d0b..6d7e0d4 100644
--- a/src/crypt.cc
+++ b/src/crypt.cc
@@ -156,6 +156,13 @@ namespace {
virtual void encrypt(uint8_t *out, const uint8_t *in);
};
+ struct ecb_encryptor_noop_impl : ecb_encryptor
+ {
+ ecb_encryptor_noop_impl() {}
+ virtual ~ecb_encryptor_noop_impl();
+ virtual void encrypt(uint8_t *out, const uint8_t *in);
+ };
+
struct ecb_decryptor_impl : ecb_decryptor
{
EVP_CIPHER_CTX ctx;
@@ -163,6 +170,13 @@ namespace {
virtual ~ecb_decryptor_impl();
virtual void decrypt(uint8_t *out, const uint8_t *in);
};
+
+ struct ecb_decryptor_noop_impl : ecb_decryptor
+ {
+ ecb_decryptor_noop_impl() {}
+ virtual ~ecb_decryptor_noop_impl();
+ virtual void decrypt(uint8_t *out, const uint8_t *in);
+ };
}
ecb_encryptor *
@@ -197,6 +211,12 @@ ecb_encryptor::create(key_generator *gen, size_t keylen)
return enc;
}
+ecb_encryptor *
+ecb_encryptor::create_noop()
+{
+ return new ecb_encryptor_noop_impl;
+}
+
ecb_decryptor *
ecb_decryptor::create(const uint8_t *key, size_t keylen)
{
@@ -229,13 +249,23 @@ ecb_decryptor::create(key_generator *gen, size_t keylen)
return dec;
}
+ecb_decryptor *
+ecb_decryptor::create_noop()
+{
+ return new ecb_decryptor_noop_impl;
+}
+
ecb_encryptor::~ecb_encryptor() {}
ecb_encryptor_impl::~ecb_encryptor_impl()
{ EVP_CIPHER_CTX_cleanup(&ctx); }
+ecb_encryptor_noop_impl::~ecb_encryptor_noop_impl()
+{}
ecb_decryptor::~ecb_decryptor() {}
ecb_decryptor_impl::~ecb_decryptor_impl()
{ EVP_CIPHER_CTX_cleanup(&ctx); }
+ecb_decryptor_noop_impl::~ecb_decryptor_noop_impl()
+{}
void
ecb_encryptor_impl::encrypt(uint8_t *out, const uint8_t *in)
@@ -247,6 +277,12 @@ ecb_encryptor_impl::encrypt(uint8_t *out, const uint8_t *in)
}
void
+ecb_encryptor_noop_impl::encrypt(uint8_t *out, const uint8_t *in)
+{
+ memcpy(out, in, AES_BLOCK_LEN);
+}
+
+void
ecb_decryptor_impl::decrypt(uint8_t *out, const uint8_t *in)
{
int olen;
@@ -255,6 +291,12 @@ ecb_decryptor_impl::decrypt(uint8_t *out, const uint8_t *in)
log_crypto_abort("ecb_decryptor::decrypt");
}
+void
+ecb_decryptor_noop_impl::decrypt(uint8_t *out, const uint8_t *in)
+{
+ memcpy(out, in, AES_BLOCK_LEN);
+}
+
namespace {
struct gcm_encryptor_impl : gcm_encryptor
{
@@ -265,6 +307,14 @@ namespace {
const uint8_t *nonce, size_t nlen);
};
+ struct gcm_encryptor_noop_impl : gcm_encryptor
+ {
+ gcm_encryptor_noop_impl() {}
+ virtual ~gcm_encryptor_noop_impl();
+ virtual void encrypt(uint8_t *out, const uint8_t *in, size_t inlen,
+ const uint8_t *nonce, size_t nlen);
+ };
+
struct gcm_decryptor_impl : gcm_decryptor
{
EVP_CIPHER_CTX ctx;
@@ -273,6 +323,14 @@ namespace {
virtual int decrypt(uint8_t *out, const uint8_t *in, size_t inlen,
const uint8_t *nonce, size_t nlen);
};
+
+ struct gcm_decryptor_noop_impl : gcm_decryptor
+ {
+ gcm_decryptor_noop_impl() {}
+ virtual ~gcm_decryptor_noop_impl();
+ virtual int decrypt(uint8_t *out, const uint8_t *in, size_t inlen,
+ const uint8_t *nonce, size_t nlen);
+ };
}
// It *appears* (from inspecting the guts of libcrypto, *not* from the
@@ -320,6 +378,12 @@ gcm_encryptor::create(key_generator *gen, size_t keylen)
return enc;
}
+gcm_encryptor *
+gcm_encryptor::create_noop()
+{
+ return new gcm_encryptor_noop_impl;
+}
+
gcm_decryptor *
gcm_decryptor::create(const uint8_t *key, size_t keylen)
{
@@ -348,12 +412,23 @@ gcm_decryptor::create(key_generator *gen, size_t keylen)
return dec;
}
+gcm_decryptor *
+gcm_decryptor::create_noop()
+{
+ return new gcm_decryptor_noop_impl;
+}
+
gcm_encryptor::~gcm_encryptor() {}
gcm_encryptor_impl::~gcm_encryptor_impl()
{ EVP_CIPHER_CTX_cleanup(&ctx); }
+gcm_encryptor_noop_impl::~gcm_encryptor_noop_impl()
+{}
+
gcm_decryptor::~gcm_decryptor() {}
gcm_decryptor_impl::~gcm_decryptor_impl()
{ EVP_CIPHER_CTX_cleanup(&ctx); }
+gcm_decryptor_noop_impl::~gcm_decryptor_noop_impl()
+{}
void
gcm_encryptor_impl::encrypt(uint8_t *out, const uint8_t *in, size_t inlen,
@@ -382,6 +457,14 @@ gcm_encryptor_impl::encrypt(uint8_t *out, const uint8_t *in, size_t inlen,
log_crypto_abort("gcm_encryptor::write tag");
}
+void
+gcm_encryptor_noop_impl::encrypt(uint8_t *out, const uint8_t *in, size_t inlen,
+ const uint8_t *, size_t)
+{
+ memcpy(out, in, inlen);
+ memset(out + inlen, 0, 16);
+}
+
int
gcm_decryptor_impl::decrypt(uint8_t *out, const uint8_t *in, size_t inlen,
const uint8_t *nonce, size_t nlen)
@@ -417,6 +500,14 @@ gcm_decryptor_impl::decrypt(uint8_t *out, const uint8_t *in, size_t inlen,
return 0;
}
+int
+gcm_decryptor_noop_impl::decrypt(uint8_t *out, const uint8_t *in, size_t inlen,
+ const uint8_t *, size_t)
+{
+ memcpy(out, in, inlen - 16);
+ return 0;
+}
+
// We use the slightly lower-level EC_* / ECDH_* routines for
// ecdh_message, instead of the EVP_PKEY_* routines, because we don't
// need algorithmic agility, and it means we only have to puzzle out
diff --git a/src/crypt.h b/src/crypt.h
index 869107a..bd6087d 100644
--- a/src/crypt.h
+++ b/src/crypt.h
@@ -51,6 +51,11 @@ struct ecb_encryptor
16, 24, or 32 bytes. */
static ecb_encryptor *create(key_generator *gen, size_t keylen);
+ /** Return a new AES/ECB encryption state that doesn't actually
+ encrypt anything -- it just copies its input to its output.
+ For testing purposes only. */
+ static ecb_encryptor *create_noop();
+
/** Encrypt exactly AES_BLOCK_LEN bytes of data in the buffer 'in' and
write the result to 'out'. */
virtual void encrypt(uint8_t *out, const uint8_t *in) = 0;
@@ -74,6 +79,11 @@ struct ecb_decryptor
16, 24, or 32 bytes. */
static ecb_decryptor *create(key_generator *gen, size_t keylen);
+ /** Return a new AES/ECB decryption state that doesn't actually
+ decrypt anything -- it just copies its input to its output.
+ For testing purposes only. */
+ static ecb_decryptor *create_noop();
+
/** Decrypt exactly AES_BLOCK_LEN bytes of data in the buffer 'in' and
write the result to 'out'. */
virtual void decrypt(uint8_t *out, const uint8_t *in) = 0;
@@ -98,6 +108,11 @@ struct gcm_encryptor
16, 24, or 32 bytes. */
static gcm_encryptor *create(key_generator *gen, size_t keylen);
+ /** Return a new AES/GCM encryption state that doesn't actually
+ encrypt anything -- it just copies its input to its output.
+ For testing purposes only. */
+ static gcm_encryptor *create_noop();
+
/** Encrypt 'inlen' bytes of data in the buffer 'in', writing the
result plus an authentication tag to the buffer 'out', whose
length must be at least 'inlen'+16 bytes. Use 'nonce'
@@ -125,6 +140,11 @@ struct gcm_decryptor
16, 24, or 32 bytes. */
static gcm_decryptor *create(key_generator *gen, size_t keylen);
+ /** Return a new AES/GCM decryption state that doesn't actually
+ decrypt anything -- it just copies its input to its output.
+ For testing purposes only. */
+ static gcm_decryptor *create_noop();
+
/** Decrypt 'inlen' bytes of data in the buffer 'in'; the last 16
bytes of this buffer are assumed to be the authentication tag.
Write the result to the buffer 'out', whose length must be at
diff --git a/src/protocol/chop.cc b/src/protocol/chop.cc
index c865c9b..bb8e906 100644
--- a/src/protocol/chop.cc
+++ b/src/protocol/chop.cc
@@ -388,6 +388,7 @@ struct chop_config_t : config_t
vector<steg_config_t *> steg_targets;
chop_circuit_table circuits;
bool trace_packets;
+ bool encryption;
CONFIG_DECLARE_METHODS(chop);
};
@@ -398,6 +399,7 @@ chop_config_t::chop_config_t()
{
ignore_socks_destination = true;
trace_packets = false;
+ encryption = true;
}
chop_config_t::~chop_config_t()
@@ -445,18 +447,24 @@ chop_config_t::init(int n_options, const char *const *options)
} else
goto usage;
- // if in client mode, accept and ignore --server-key=
- if (mode != LSN_SIMPLE_SERVER &&
- !strncmp(options[1], "--server-key=", 13)) {
- options++;
- n_options--;
- }
-
- if (!strcmp(options[1], "--trace-packets")) {
+ while (options[1][0] == '-') {
+ if (!strncmp(options[1], "--server-key=", 13)) {
+ // accept and ignore (for now) client only
+ if (mode == LSN_SIMPLE_SERVER) {
+ log_warn("chop: --server-key option is not valid in server mode");
+ goto usage;
+ }
+ } else if (!strcmp(options[1], "--trace-packets")) {
+ trace_packets = true;
+ log_enable_timestamps();
+ } else if (!strcmp(options[1], "--disable-encryption")) {
+ encryption = false;
+ } else {
+ log_warn("chop: unrecognized option '%s'", options[1]);
+ goto usage;
+ }
options++;
n_options--;
- trace_packets = true;
- log_enable_timestamps();
}
up_address = resolve_address_port(options[1], 1, listen_up, defport);
@@ -550,21 +558,37 @@ chop_config_t::circuit_create(size_t)
chop_circuit_t *ckt = new chop_circuit_t;
ckt->config = this;
- key_generator *kgen =
- key_generator::from_passphrase((const uint8_t *)passphrase,
- sizeof(passphrase) - 1,
- 0, 0, 0, 0);
+ key_generator *kgen = 0;
+
+ if (encryption)
+ kgen = key_generator::from_passphrase((const uint8_t *)passphrase,
+ sizeof(passphrase) - 1,
+ 0, 0, 0, 0);
if (mode == LSN_SIMPLE_SERVER) {
- ckt->send_crypt = gcm_encryptor::create(kgen, 16);
- ckt->send_hdr_crypt = ecb_encryptor::create(kgen, 16);
- ckt->recv_crypt = gcm_decryptor::create(kgen, 16);
- ckt->recv_hdr_crypt = ecb_decryptor::create(kgen, 16);
+ if (encryption) {
+ ckt->send_crypt = gcm_encryptor::create(kgen, 16);
+ ckt->send_hdr_crypt = ecb_encryptor::create(kgen, 16);
+ ckt->recv_crypt = gcm_decryptor::create(kgen, 16);
+ ckt->recv_hdr_crypt = ecb_decryptor::create(kgen, 16);
+ } else {
+ ckt->send_crypt = gcm_encryptor::create_noop();
+ ckt->send_hdr_crypt = ecb_encryptor::create_noop();
+ ckt->recv_crypt = gcm_decryptor::create_noop();
+ ckt->recv_hdr_crypt = ecb_decryptor::create_noop();
+ }
} else {
- ckt->recv_crypt = gcm_decryptor::create(kgen, 16);
- ckt->recv_hdr_crypt = ecb_decryptor::create(kgen, 16);
- ckt->send_crypt = gcm_encryptor::create(kgen, 16);
- ckt->send_hdr_crypt = ecb_encryptor::create(kgen, 16);
+ if (encryption) {
+ ckt->recv_crypt = gcm_decryptor::create(kgen, 16);
+ ckt->recv_hdr_crypt = ecb_decryptor::create(kgen, 16);
+ ckt->send_crypt = gcm_encryptor::create(kgen, 16);
+ ckt->send_hdr_crypt = ecb_encryptor::create(kgen, 16);
+ } else {
+ ckt->recv_crypt = gcm_decryptor::create_noop();
+ ckt->recv_hdr_crypt = ecb_decryptor::create_noop();
+ ckt->send_crypt = gcm_encryptor::create_noop();
+ ckt->send_hdr_crypt = ecb_encryptor::create_noop();
+ }
std::pair<chop_circuit_table::iterator, bool> out;
do {