Merge branch 'maint-0.2.2' into release-0.2.2

This commit is contained in:
Roger Dingledine 2012-04-05 16:32:07 -04:00
commit 14e3900393
22 changed files with 20403 additions and 6803 deletions

11
changes/bridgepassword Normal file
View File

@ -0,0 +1,11 @@
o Security fixes:
- When using the debuging BridgePassword field, a bridge authority
now compares alleged passwords by hashing them, then comparing
the result to a digest of the expected authenticator. This avoids
a potential side-channel attack in the previous code, which
had foolishly used strcmp(). Fortunately, the BridgePassword field
*is not in use*, but if it had been, the timing
behavior of strcmp() might have allowed an adversary to guess the
BridgePassword value, and enumerate the bridges. Bugfix on
0.2.0.14-alpha. Fixes bug 5543.

7
changes/bug5090 Normal file
View File

@ -0,0 +1,7 @@
o Minor bugfixes:
- Detect and reject certain misformed escape sequences in configuration
values. Previously, these values would cause us to crash if received
in a torrc file or over an (authenticated) control port. Bug found by
Esteban Manchado Velázquez. Patch by Alexander Schrijver. Fix for
bug 5090; bugfix on 0.2.0.16-alpha.

3
changes/bug5340 Normal file
View File

@ -0,0 +1,3 @@
o Minor bugfixes:
- Fix a compile warning when using the --enable-openbsd-malloc configure
option. Fixes bug 5340; bugfix on 0.2.0.20-rc.

3
changes/bug5342 Normal file
View File

@ -0,0 +1,3 @@
o Security fixes:
- Never use a bridge as an exit, even if it claims to be one. Found by
wanoskarnet. Fixes bug 5342. Bugfix on ????.

7
changes/bug5343 Normal file
View File

@ -0,0 +1,7 @@
o Security fixes:
- Only build circuits if we have a sufficient threshold of the total
descriptors marked in the consensus with the "Exit" flag. This
mitigates an attack proposed by wanoskarnet, in which all of a
client's bridges collude to restrict the exit nodes that the
client knows about. Fixes bug 5343.

3
changes/geoip-march2012 Normal file
View File

@ -0,0 +1,3 @@
o Minor features:
- Update to the March 6 2012 Maxmind GeoLite Country database.

View File

@ -0,0 +1,4 @@
o Directory authority changes:
- Change IP address for ides (v3 directory authority), and rename it to
turtles.

9
changes/safecookie Normal file
View File

@ -0,0 +1,9 @@
o Security Features:
- Provide controllers with a safer way to implement the cookie
authentication mechanism. With the old method, if another locally
running program could convince a controller that it was the Tor
process, then that program could trick the contoller into
telling it the contents of an arbitrary 32-byte file. The new
"SAFECOOKIE" authentication method uses a challenge-response
approach to prevent this. Fixes bug 5185, implements proposal 193.

View File

@ -1297,8 +1297,11 @@ DIRECTORY AUTHORITY SERVER OPTIONS
**BridgePassword** __Password__::
If set, contains an HTTP authenticator that tells a bridge authority to
serve all requested bridge information. Used for debugging. (Default:
not set.)
serve all requested bridge information. Used by the (only partially
implemented) "bridge community" design, where a community of bridge
relay operators all use an alternate bridge directory authority,
and their target user audience can periodically fetch the list of
available community bridges to stay up-to-date. (Default: not set.)
**V3AuthVotingInterval** __N__ **minutes**|**hours**::
V3 authoritative directories only. Configures the server's preferred voting

View File

@ -285,6 +285,8 @@ static void *imalloc(size_t size);
static void ifree(void *ptr);
static void *irealloc(void *ptr, size_t size);
static void *malloc_bytes(size_t size);
void *memalign(size_t boundary, size_t size);
size_t malloc_good_size(size_t size);
/*
* Function for page directory lookup.
@ -1980,10 +1982,11 @@ static int ispowerof2 (size_t a) {
int posix_memalign(void **memptr, size_t alignment, size_t size)
{
void *r;
size_t max;
if ((alignment < PTR_SIZE) || (alignment%PTR_SIZE != 0)) return EINVAL;
if (!ispowerof2(alignment)) return EINVAL;
if (alignment < malloc_minsize) alignment = malloc_minsize;
size_t max = alignment > size ? alignment : size;
max = alignment > size ? alignment : size;
if (alignment <= malloc_pagesize)
r = malloc(max);
else {

View File

@ -1714,6 +1714,74 @@ crypto_hmac_sha1(char *hmac_out,
(unsigned char*)hmac_out, NULL);
}
/** Compute the HMAC-SHA-256 of the <b>msg_len</b> bytes in <b>msg</b>, using
* the <b>key</b> of length <b>key_len</b>. Store the DIGEST_LEN-byte result
* in <b>hmac_out</b>.
*/
void
crypto_hmac_sha256(char *hmac_out,
const char *key, size_t key_len,
const char *msg, size_t msg_len)
{
#if (OPENSSL_VERSION_NUMBER >= 0x00908000l)
/* If we've got OpenSSL >=0.9.8 we can use its hmac implementation. */
tor_assert(key_len < INT_MAX);
tor_assert(msg_len < INT_MAX);
HMAC(EVP_sha256(), key, (int)key_len, (unsigned char*)msg, (int)msg_len,
(unsigned char*)hmac_out, NULL);
#else
/* OpenSSL doesn't have an EVP implementation for SHA256. We'll need
to do HMAC on our own.
HMAC isn't so hard: To compute HMAC(key, msg):
1. If len(key) > blocksize, key = H(key).
2. If len(key) < blocksize, right-pad key up to blocksize with 0 bytes.
3. let ipad = key xor 0x363636363636....36
let opad = key xor 0x5c5c5c5c5c5c....5c
The result is H(opad | H( ipad | msg ) )
*/
#define BLOCKSIZE 64
#define DIGESTSIZE 32
uint8_t k[BLOCKSIZE];
uint8_t pad[BLOCKSIZE];
uint8_t d[DIGESTSIZE];
int i;
SHA256_CTX st;
tor_assert(key_len < INT_MAX);
tor_assert(msg_len < INT_MAX);
if (key_len <= BLOCKSIZE) {
memset(k, 0, sizeof(k));
memcpy(k, key, key_len); /* not time invariant in key_len */
} else {
SHA256((const uint8_t *)key, key_len, k);
memset(k+DIGESTSIZE, 0, sizeof(k)-DIGESTSIZE);
}
for (i = 0; i < BLOCKSIZE; ++i)
pad[i] = k[i] ^ 0x36;
SHA256_Init(&st);
SHA256_Update(&st, pad, BLOCKSIZE);
SHA256_Update(&st, (uint8_t*)msg, msg_len);
SHA256_Final(d, &st);
for (i = 0; i < BLOCKSIZE; ++i)
pad[i] = k[i] ^ 0x5c;
SHA256_Init(&st);
SHA256_Update(&st, pad, BLOCKSIZE);
SHA256_Update(&st, d, DIGESTSIZE);
SHA256_Final((uint8_t*)hmac_out, &st);
/* Now clear everything. */
memset(k, 0, sizeof(k));
memset(pad, 0, sizeof(pad));
memset(d, 0, sizeof(d));
memset(&st, 0, sizeof(st));
#undef BLOCKSIZE
#undef DIGESTSIZE
#endif
}
/* DH */
/** Shared P parameter for our circuit-crypto DH key exchanges. */

View File

@ -195,6 +195,9 @@ void crypto_digest_assign(crypto_digest_env_t *into,
void crypto_hmac_sha1(char *hmac_out,
const char *key, size_t key_len,
const char *msg, size_t msg_len);
void crypto_hmac_sha256(char *hmac_out,
const char *key, size_t key_len,
const char *msg, size_t msg_len);
/* Key negotiation */
#define DH_TYPE_CIRCUIT 1

View File

@ -2212,14 +2212,16 @@ unescape_string(const char *s, char **result, size_t *size_out)
case '\"':
goto end_of_loop;
case '\\':
if ((cp[1] == 'x' || cp[1] == 'X')
&& TOR_ISXDIGIT(cp[2]) && TOR_ISXDIGIT(cp[3])) {
if (cp[1] == 'x' || cp[1] == 'X') {
if (!(TOR_ISXDIGIT(cp[2]) && TOR_ISXDIGIT(cp[3])))
return NULL;
cp += 4;
} else if (TOR_ISODIGIT(cp[1])) {
cp += 2;
if (TOR_ISODIGIT(*cp)) ++cp;
if (TOR_ISODIGIT(*cp)) ++cp;
} else if (cp[1]) {
} else if (cp[1] == 'n' || cp[1] == 'r' || cp[1] == 't' || cp[1] == '"'
|| cp[1] == '\\' || cp[1] == '\'') {
cp += 2;
} else {
return NULL;
@ -2251,9 +2253,19 @@ unescape_string(const char *s, char **result, size_t *size_out)
case 'r': *out++ = '\r'; cp += 2; break;
case 't': *out++ = '\t'; cp += 2; break;
case 'x': case 'X':
*out++ = ((hex_decode_digit(cp[2])<<4) +
hex_decode_digit(cp[3]));
cp += 4;
{
int x1, x2;
x1 = hex_decode_digit(cp[2]);
x2 = hex_decode_digit(cp[3]);
if (x1 == -1 || x2 == -1) {
tor_free(*result);
return NULL;
}
*out++ = ((x1<<4) + x2);
cp += 4;
}
break;
case '0': case '1': case '2': case '3': case '4': case '5':
case '6': case '7':

File diff suppressed because it is too large Load Diff

View File

@ -2704,7 +2704,11 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
n_supported[i] = -1;
continue; /* skip routers that are known to be down or bad exits */
}
if (router->purpose != ROUTER_PURPOSE_GENERAL) {
/* never pick a non-general node as a random exit. */
n_supported[i] = -1;
continue;
}
if (options->_ExcludeExitNodesUnion &&
routerset_contains_router(options->_ExcludeExitNodesUnion, router)) {
n_supported[i] = -1;

View File

@ -713,6 +713,7 @@ or_options_free(or_options_t *options)
return;
routerset_free(options->_ExcludeExitNodesUnion);
tor_free(options->_BridgePassword_AuthDigest);
config_free(&options_format, options);
}
@ -808,8 +809,9 @@ add_default_trusted_dir_authorities(authority_type_t type)
"194.109.206.212:80 7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755",
"Tonga orport=443 bridge no-v2 82.94.251.203:80 "
"4A0C CD2D DC79 9508 3D73 F5D6 6710 0C8A 5831 F16D",
"ides orport=9090 no-v2 v3ident=27B6B5996C426270A5C95488AA5BCEB6BCC86956 "
"216.224.124.114:9030 F397 038A DC51 3361 35E7 B80B D99C A384 4360 292B",
"turtles orport=9090 no-v2 "
"v3ident=27B6B5996C426270A5C95488AA5BCEB6BCC86956 "
"76.73.17.194:9030 F397 038A DC51 3361 35E7 B80B D99C A384 4360 292B",
"gabelmoo orport=443 no-v2 "
"v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 "
"212.112.245.170:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281",
@ -1298,6 +1300,24 @@ options_act(or_options_t *old_options)
/* Change the cell EWMA settings */
cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus());
/* Update the BridgePassword's hashed version as needed. We store this as a
* digest so that we can do side-channel-proof comparisons on it.
*/
if (options->BridgePassword) {
char *http_authenticator;
http_authenticator = alloc_http_authenticator(options->BridgePassword);
if (!http_authenticator) {
log_warn(LD_BUG, "Unable to allocate HTTP authenticator. Not setting "
"BridgePassword.");
return -1;
}
options->_BridgePassword_AuthDigest = tor_malloc(DIGEST256_LEN);
crypto_digest256(options->_BridgePassword_AuthDigest,
http_authenticator, strlen(http_authenticator),
DIGEST_SHA256);
tor_free(http_authenticator);
}
/* Check for transitions that need action. */
if (old_options) {
int revise_trackexithosts = 0;

View File

@ -419,6 +419,7 @@ _connection_free(connection_t *conn)
}
if (conn->type == CONN_TYPE_CONTROL) {
control_connection_t *control_conn = TO_CONTROL_CONN(conn);
tor_free(control_conn->safecookie_client_hash);
tor_free(control_conn->incoming_cmd);
}

View File

@ -101,6 +101,12 @@ static int authentication_cookie_is_set = 0;
* read it off disk, it has permission to connect.) */
static char authentication_cookie[AUTHENTICATION_COOKIE_LEN];
#define SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT \
"Tor safe cookie authentication server-to-controller hash"
#define SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT \
"Tor safe cookie authentication controller-to-server hash"
#define SAFECOOKIE_SERVER_NONCE_LEN DIGEST256_LEN
/** A sufficiently large size to record the last bootstrap phase string. */
#define BOOTSTRAP_MSG_LEN 1024
@ -1078,6 +1084,32 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
used_quoted_string = 1;
}
if (conn->safecookie_client_hash != NULL) {
/* The controller has chosen safe cookie authentication; the only
* acceptable authentication value is the controller-to-server
* response. */
tor_assert(authentication_cookie_is_set);
if (password_len != DIGEST256_LEN) {
log_warn(LD_CONTROL,
"Got safe cookie authentication response with wrong length "
"(%d)", (int)password_len);
errstr = "Wrong length for safe cookie response.";
goto err;
}
if (tor_memneq(conn->safecookie_client_hash, password, DIGEST256_LEN)) {
log_warn(LD_CONTROL,
"Got incorrect safe cookie authentication response");
errstr = "Safe cookie response did not match expected value.";
goto err;
}
tor_free(conn->safecookie_client_hash);
goto ok;
}
if (!options->CookieAuthentication && !options->HashedControlPassword &&
!options->HashedControlSessionPassword) {
/* if Tor doesn't demand any stronger authentication, then
@ -2758,8 +2790,10 @@ handle_control_protocolinfo(control_connection_t *conn, uint32_t len,
int passwd = (options->HashedControlPassword != NULL ||
options->HashedControlSessionPassword != NULL);
smartlist_t *mlist = smartlist_create();
if (cookies)
if (cookies) {
smartlist_add(mlist, (char*)"COOKIE");
smartlist_add(mlist, (char*)"SAFECOOKIE");
}
if (passwd)
smartlist_add(mlist, (char*)"HASHEDPASSWORD");
if (!cookies && !passwd)
@ -2787,6 +2821,121 @@ handle_control_protocolinfo(control_connection_t *conn, uint32_t len,
return 0;
}
/** Called when we get an AUTHCHALLENGE command. */
static int
handle_control_authchallenge(control_connection_t *conn, uint32_t len,
const char *body)
{
const char *cp = body;
char *client_nonce;
size_t client_nonce_len;
char server_hash[DIGEST256_LEN];
char server_hash_encoded[HEX_DIGEST256_LEN+1];
char server_nonce[SAFECOOKIE_SERVER_NONCE_LEN];
char server_nonce_encoded[(2*SAFECOOKIE_SERVER_NONCE_LEN) + 1];
cp += strspn(cp, " \t\n\r");
if (!strcasecmpstart(cp, "SAFECOOKIE")) {
cp += strlen("SAFECOOKIE");
} else {
connection_write_str_to_buf("513 AUTHCHALLENGE only supports SAFECOOKIE "
"authentication", conn);
connection_mark_for_close(TO_CONN(conn));
return -1;
}
if (!authentication_cookie_is_set) {
connection_write_str_to_buf("515 Cookie authentication is disabled", conn);
connection_mark_for_close(TO_CONN(conn));
return -1;
}
cp += strspn(cp, " \t\n\r");
if (*cp == '"') {
const char *newcp =
decode_escaped_string(cp, len - (cp - body),
&client_nonce, &client_nonce_len);
if (newcp == NULL) {
connection_write_str_to_buf("513 Invalid quoted client nonce",
conn);
connection_mark_for_close(TO_CONN(conn));
return -1;
}
cp = newcp;
} else {
size_t client_nonce_encoded_len = strspn(cp, "0123456789ABCDEFabcdef");
client_nonce_len = client_nonce_encoded_len / 2;
client_nonce = tor_malloc_zero(client_nonce_len);
if (base16_decode(client_nonce, client_nonce_len,
cp, client_nonce_encoded_len) < 0) {
connection_write_str_to_buf("513 Invalid base16 client nonce",
conn);
connection_mark_for_close(TO_CONN(conn));
return -1;
}
cp += client_nonce_encoded_len;
}
cp += strspn(cp, " \t\n\r");
if (*cp != '\0' ||
cp != body + len) {
connection_write_str_to_buf("513 Junk at end of AUTHCHALLENGE command",
conn);
connection_mark_for_close(TO_CONN(conn));
tor_free(client_nonce);
return -1;
}
tor_assert(!crypto_rand(server_nonce, SAFECOOKIE_SERVER_NONCE_LEN));
/* Now compute and send the server-to-controller response, and the
* server's nonce. */
tor_assert(authentication_cookie != NULL);
{
size_t tmp_len = (AUTHENTICATION_COOKIE_LEN +
client_nonce_len +
SAFECOOKIE_SERVER_NONCE_LEN);
char *tmp = tor_malloc_zero(tmp_len);
char *client_hash = tor_malloc_zero(DIGEST256_LEN);
memcpy(tmp, authentication_cookie, AUTHENTICATION_COOKIE_LEN);
memcpy(tmp + AUTHENTICATION_COOKIE_LEN, client_nonce, client_nonce_len);
memcpy(tmp + AUTHENTICATION_COOKIE_LEN + client_nonce_len,
server_nonce, SAFECOOKIE_SERVER_NONCE_LEN);
crypto_hmac_sha256(server_hash,
SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT,
strlen(SAFECOOKIE_SERVER_TO_CONTROLLER_CONSTANT),
tmp,
tmp_len);
crypto_hmac_sha256(client_hash,
SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT,
strlen(SAFECOOKIE_CONTROLLER_TO_SERVER_CONSTANT),
tmp,
tmp_len);
conn->safecookie_client_hash = client_hash;
tor_free(tmp);
}
base16_encode(server_hash_encoded, sizeof(server_hash_encoded),
server_hash, sizeof(server_hash));
base16_encode(server_nonce_encoded, sizeof(server_nonce_encoded),
server_nonce, sizeof(server_nonce));
connection_printf_to_buf(conn,
"250 AUTHCHALLENGE SERVERHASH=%s "
"SERVERNONCE=%s\r\n",
server_hash_encoded,
server_nonce_encoded);
return 0;
}
/** Called when we get a USEFEATURE command: parse the feature list, and
* set up the control_connection's options properly. */
static int
@ -2888,7 +3037,10 @@ is_valid_initial_command(control_connection_t *conn, const char *cmd)
if (conn->_base.state == CONTROL_CONN_STATE_OPEN)
return 1;
if (!strcasecmp(cmd, "PROTOCOLINFO"))
return !conn->have_sent_protocolinfo;
return (!conn->have_sent_protocolinfo &&
conn->safecookie_client_hash == NULL);
if (!strcasecmp(cmd, "AUTHCHALLENGE"))
return (conn->safecookie_client_hash == NULL);
if (!strcasecmp(cmd, "AUTHENTICATE") ||
!strcasecmp(cmd, "QUIT"))
return 1;
@ -3104,6 +3256,9 @@ connection_control_process_inbuf(control_connection_t *conn)
} else if (!strcasecmp(conn->incoming_cmd, "PROTOCOLINFO")) {
if (handle_control_protocolinfo(conn, cmd_data_len, args))
return -1;
} else if (!strcasecmp(conn->incoming_cmd, "AUTHCHALLENGE")) {
if (handle_control_authchallenge(conn, cmd_data_len, args))
return -1;
} else {
connection_printf_to_buf(conn, "510 Unrecognized command \"%s\"\r\n",
conn->incoming_cmd);

View File

@ -3069,22 +3069,24 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
}
if (options->BridgeAuthoritativeDir &&
options->BridgePassword &&
options->_BridgePassword_AuthDigest &&
connection_dir_is_encrypted(conn) &&
!strcmp(url,"/tor/networkstatus-bridges")) {
char *status;
char *secret = alloc_http_authenticator(options->BridgePassword);
char digest[DIGEST256_LEN];
header = http_get_header(headers, "Authorization: Basic ");
if (header)
crypto_digest256(digest, header, strlen(header), DIGEST_SHA256);
/* now make sure the password is there and right */
if (!header || strcmp(header, secret)) {
if (!header ||
tor_memneq(digest,
options->_BridgePassword_AuthDigest, DIGEST256_LEN)) {
write_http_status_line(conn, 404, "Not found");
tor_free(secret);
tor_free(header);
goto done;
}
tor_free(secret);
tor_free(header);
/* all happy now. send an answer. */

View File

@ -1254,6 +1254,12 @@ typedef struct control_connection_t {
* connection. */
unsigned int is_owning_control_connection:1;
/** If we have sent an AUTHCHALLENGE reply on this connection and
* have not received a successful AUTHENTICATE command, points to
* the value which the client must send to authenticate itself;
* otherwise, NULL. */
char *safecookie_client_hash;
/** Amount of space allocated in incoming_cmd. */
uint32_t incoming_cmd_len;
/** Number of bytes currently stored in incoming_cmd. */
@ -2483,10 +2489,11 @@ typedef struct {
* that aggregates bridge descriptors? */
/** If set on a bridge authority, it will answer requests on its dirport
* for bridge statuses -- but only if the requests use this password.
* If set on a bridge user, request bridge statuses, and use this password
* when doing so. */
* for bridge statuses -- but only if the requests use this password. */
char *BridgePassword;
/** If BridgePassword is set, this is a SHA256 digest of the basic http
* authenticator for it. Used so we can do a time-independent comparison. */
char *_BridgePassword_AuthDigest;
int UseBridges; /**< Boolean: should we start all circuits with a bridge? */
config_line_t *Bridges; /**< List of bootstrap bridge addresses. */

View File

@ -4788,18 +4788,21 @@ get_dir_info_status_string(void)
* them seem like ones we'd use, and how many of <em>those</em> we have
* descriptors for. Store the former in *<b>num_usable</b> and the latter in
* *<b>num_present</b>. If <b>in_set</b> is non-NULL, only consider those
* routers in <b>in_set</b>.
* routers in <b>in_set</b>. If <b>exit_only</b> is true, only consider nodes
* with the Exit flag.
*/
static void
count_usable_descriptors(int *num_present, int *num_usable,
const networkstatus_t *consensus,
or_options_t *options, time_t now,
routerset_t *in_set)
routerset_t *in_set, int exit_only)
{
*num_present = 0, *num_usable=0;
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
{
if (exit_only && ! rs->is_exit)
continue;
if (in_set && ! routerset_contains_routerstatus(in_set, rs))
continue;
if (client_would_use_router(rs, now, options)) {
@ -4830,7 +4833,7 @@ count_loading_descriptors_progress(void)
return 0; /* can't count descriptors if we have no list of them */
count_usable_descriptors(&num_present, &num_usable,
consensus, get_options(), now, NULL);
consensus, get_options(), now, NULL, 0);
if (num_usable == 0)
return 0; /* don't div by 0 */
@ -4849,6 +4852,7 @@ static void
update_router_have_minimum_dir_info(void)
{
int num_present = 0, num_usable=0;
int num_exit_present = 0, num_exit_usable = 0;
time_t now = time(NULL);
int res;
or_options_t *options = get_options();
@ -4875,7 +4879,9 @@ update_router_have_minimum_dir_info(void)
}
count_usable_descriptors(&num_present, &num_usable, consensus, options, now,
NULL);
NULL, 0);
count_usable_descriptors(&num_exit_present, &num_exit_usable,
consensus, options, now, options->ExitNodes, 1);
if (num_present < num_usable/4) {
tor_snprintf(dir_info_status, sizeof(dir_info_status),
@ -4889,12 +4895,19 @@ update_router_have_minimum_dir_info(void)
num_present, num_present ? "" : "s");
res = 0;
goto done;
} else if (num_exit_present < num_exit_usable / 3) {
tor_snprintf(dir_info_status, sizeof(dir_info_status),
"We have only %d/%d usable exit node descriptors.",
num_exit_present, num_exit_usable);
res = 0;
control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0);
goto done;
}
/* Check for entry nodes. */
if (options->EntryNodes) {
count_usable_descriptors(&num_present, &num_usable, consensus, options,
now, options->EntryNodes);
now, options->EntryNodes, 0);
if (!num_usable || !num_present) {
tor_snprintf(dir_info_status, sizeof(dir_info_status),

View File

@ -231,7 +231,7 @@ test_crypto_sha(void)
{
crypto_digest_env_t *d1 = NULL, *d2 = NULL;
int i;
char key[80];
char key[160];
char digest[32];
char data[50];
char d_out1[DIGEST_LEN], d_out2[DIGEST256_LEN];
@ -276,6 +276,75 @@ test_crypto_sha(void)
test_streq(hex_str(digest, 20),
"AA4AE5E15272D00E95705637CE8A3B55ED402112");
/* Test HMAC-SHA256 with test cases from wikipedia and RFC 4231 */
/* Case empty (wikipedia) */
crypto_hmac_sha256(digest, "", 0, "", 0);
test_streq(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),
"F7BC83F430538424B13298E6AA6FB143EF4D59A14946175997479DBC2D1A3CD8");
/* "Test Case 1" from RFC 4231 */
memset(key, 0x0b, 20);
crypto_hmac_sha256(digest, key, 20, "Hi There", 8);
test_memeq_hex(digest,
"b0344c61d8db38535ca8afceaf0bf12b"
"881dc200c9833da726e9376c2e32cff7");
/* "Test Case 2" from RFC 4231 */
memset(key, 0x0b, 20);
crypto_hmac_sha256(digest, "Jefe", 4, "what do ya want for nothing?", 28);
test_memeq_hex(digest,
"5bdcc146bf60754e6a042426089575c7"
"5a003f089d2739839dec58b964ec3843");
/* "Test case 3" from RFC 4231 */
memset(key, 0xaa, 20);
memset(data, 0xdd, 50);
crypto_hmac_sha256(digest, key, 20, data, 50);
test_memeq_hex(digest,
"773ea91e36800e46854db8ebd09181a7"
"2959098b3ef8c122d9635514ced565fe");
/* "Test case 4" from RFC 4231 */
base16_decode(key, 25,
"0102030405060708090a0b0c0d0e0f10111213141516171819", 50);
memset(data, 0xcd, 50);
crypto_hmac_sha256(digest, key, 25, data, 50);
test_memeq_hex(digest,
"82558a389a443c0ea4cc819899f2083a"
"85f0faa3e578f8077a2e3ff46729665b");
/* "Test case 5" from RFC 4231 */
memset(key, 0x0c, 20);
crypto_hmac_sha256(digest, key, 20, "Test With Truncation", 20);
test_memeq_hex(digest,
"a3b6167473100ee06e0c796c2955552b");
/* "Test case 6" from RFC 4231 */
memset(key, 0xaa, 131);
crypto_hmac_sha256(digest, key, 131,
"Test Using Larger Than Block-Size Key - Hash Key First",
54);
test_memeq_hex(digest,
"60e431591ee0b67f0d8a26aacbf5b77f"
"8e0bc6213728c5140546040f0ee37f54");
/* "Test case 7" from RFC 4231 */
memset(key, 0xaa, 131);
crypto_hmac_sha256(digest, key, 131,
"This is a test using a larger than block-size key and a "
"larger than block-size data. The key needs to be hashed "
"before being used by the HMAC algorithm.", 152);
test_memeq_hex(digest,
"9b09ffa71b942fcb27635fbcd5b0e944"
"bfdc63644f0713938a7f51535c3a35e2");
/* Incremental digest code. */
d1 = crypto_new_digest_env();
test_assert(d1);