tor-commits
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
November 2016
- 16 participants
- 1665 discussions

[tor/master] Migrate certificates into a sub-structure of or_handshake_state
by nickm@torproject.org 03 Nov '16
by nickm@torproject.org 03 Nov '16
03 Nov '16
commit e23389841c7797615b09ee6457e841b4ed13ea75
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu May 21 13:43:34 2015 -0400
Migrate certificates into a sub-structure of or_handshake_state
This will help us do cert-checking in the background in the future,
perhaps.
---
src/or/channeltls.c | 16 ++++++++--------
src/or/connection_or.c | 10 +++++-----
src/or/or.h | 19 ++++++++++---------
src/or/torcert.c | 20 ++++++++++++++++++++
src/or/torcert.h | 3 +++
src/test/test_link_handshake.c | 32 ++++++++++++++++----------------
6 files changed, 62 insertions(+), 38 deletions(-)
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index 9e92aad..fbe784c 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -1947,7 +1947,7 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
"Got some good certificates from %s:%d: Authenticated it.",
safe_str(chan->conn->base_.address), chan->conn->base_.port);
- chan->conn->handshake_state->id_cert = id_cert;
+ chan->conn->handshake_state->certs->id_cert = id_cert;
x509_certs[OR_CERT_TYPE_ID_1024] = NULL;
if (!public_server_mode(get_options())) {
@@ -1973,8 +1973,8 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
chan->conn->base_.port);
/* XXXX check more stuff? */
- chan->conn->handshake_state->id_cert = id_cert;
- chan->conn->handshake_state->auth_cert = auth_cert;
+ chan->conn->handshake_state->certs->id_cert = id_cert;
+ chan->conn->handshake_state->certs->auth_cert = auth_cert;
x509_certs[OR_CERT_TYPE_ID_1024] = x509_certs[OR_CERT_TYPE_AUTH_1024]
= NULL;
}
@@ -2147,9 +2147,9 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
}
if (!(chan->conn->handshake_state->received_certs_cell))
ERR("We never got a certs cell");
- if (chan->conn->handshake_state->auth_cert == NULL)
+ if (chan->conn->handshake_state->certs->auth_cert == NULL)
ERR("We never got an authentication certificate");
- if (chan->conn->handshake_state->id_cert == NULL)
+ if (chan->conn->handshake_state->certs->id_cert == NULL)
ERR("We never got an identity certificate");
if (cell->payload_len < 4)
ERR("Cell was way too short");
@@ -2195,7 +2195,7 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
{
crypto_pk_t *pk = tor_tls_cert_get_key(
- chan->conn->handshake_state->auth_cert);
+ chan->conn->handshake_state->certs->auth_cert);
char d[DIGEST256_LEN];
char *signed_data;
size_t keysize;
@@ -2234,9 +2234,9 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
chan->conn->handshake_state->digest_received_data = 0;
{
crypto_pk_t *identity_rcvd =
- tor_tls_cert_get_key(chan->conn->handshake_state->id_cert);
+ tor_tls_cert_get_key(chan->conn->handshake_state->certs->id_cert);
const common_digests_t *id_digests =
- tor_x509_cert_get_id_digests(chan->conn->handshake_state->id_cert);
+ tor_x509_cert_get_id_digests(chan->conn->handshake_state->certs->id_cert);
/* This must exist; we checked key type when reading the cert. */
tor_assert(id_digests);
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index ed91595..5a9c597 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -1764,6 +1764,7 @@ connection_init_or_handshake_state(or_connection_t *conn, int started_here)
s->started_here = started_here ? 1 : 0;
s->digest_sent_data = 1;
s->digest_received_data = 1;
+ s->certs = or_handshake_certs_new();
return 0;
}
@@ -1775,8 +1776,7 @@ or_handshake_state_free(or_handshake_state_t *state)
return;
crypto_digest_free(state->digest_sent);
crypto_digest_free(state->digest_received);
- tor_x509_cert_free(state->auth_cert);
- tor_x509_cert_free(state->id_cert);
+ or_handshake_certs_free(state->certs);
memwipe(state, 0xBE, sizeof(or_handshake_state_t));
tor_free(state);
}
@@ -2356,7 +2356,7 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
goto err;
my_digests = tor_x509_cert_get_id_digests(id_cert);
their_digests =
- tor_x509_cert_get_id_digests(conn->handshake_state->id_cert);
+ tor_x509_cert_get_id_digests(conn->handshake_state->certs->id_cert);
tor_assert(my_digests);
tor_assert(their_digests);
my_id = (uint8_t*)my_digests->d[DIGEST_SHA256];
@@ -2374,10 +2374,10 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
if (is_ed) {
const ed25519_public_key_t *my_ed_id, *their_ed_id;
- if (!conn->handshake_state->ed_id_sign_cert)
+ if (!conn->handshake_state->certs->ed_id_sign_cert)
goto err;
my_ed_id = get_master_identity_key();
- their_ed_id = &conn->handshake_state->ed_id_sign_cert->signing_key;
+ their_ed_id = &conn->handshake_state->certs->ed_id_sign_cert->signing_key;
const uint8_t *cid_ed = (server ? their_ed_id : my_ed_id)->pubkey;
const uint8_t *sid_ed = (server ? my_ed_id : their_ed_id)->pubkey;
diff --git a/src/or/or.h b/src/or/or.h
index 9e9b1bf..cdde448 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1386,6 +1386,15 @@ typedef struct listener_connection_t {
* signs. */
#define V3_AUTH_BODY_LEN (V3_AUTH_FIXED_PART_LEN + 8 + 16)
+typedef struct or_handshake_certs_t {
+ /** The cert for the key that's supposed to sign the AUTHENTICATE cell */
+ tor_x509_cert_t *auth_cert;
+ /** A self-signed identity certificate */
+ tor_x509_cert_t *id_cert;
+ /** DOCDOC */
+ struct tor_cert_st *ed_id_sign_cert;
+} or_handshake_certs_t;
+
/** Stores flags and information related to the portion of a v2/v3 Tor OR
* connection handshake that happens after the TLS handshake is finished.
*/
@@ -1438,16 +1447,8 @@ typedef struct or_handshake_state_t {
/** Certificates that a connection initiator sent us in a CERTS cell; we're
* holding on to them until we get an AUTHENTICATE cell.
- *
- * @{
*/
- /** The cert for the key that's supposed to sign the AUTHENTICATE cell */
- tor_x509_cert_t *auth_cert;
- /** A self-signed identity certificate */
- tor_x509_cert_t *id_cert;
- /** DOCDOC */
- struct tor_cert_st *ed_id_sign_cert;
- /**@}*/
+ or_handshake_certs_t *certs;
} or_handshake_state_t;
/** Length of Extended ORPort connection identifier. */
diff --git a/src/or/torcert.c b/src/or/torcert.c
index a6a33c6..e8bee54 100644
--- a/src/or/torcert.c
+++ b/src/or/torcert.c
@@ -8,6 +8,7 @@
* protocol.
*/
+#include "or.h"
#include "crypto.h"
#include "torcert.h"
#include "ed25519_cert.h"
@@ -295,3 +296,22 @@ tor_make_rsa_ed25519_crosscert(const ed25519_public_key_t *ed_key,
return sz;
}
+or_handshake_certs_t *
+or_handshake_certs_new(void)
+{
+ return tor_malloc_zero(sizeof(or_handshake_certs_t));
+}
+
+/** DODCDOC */
+void
+or_handshake_certs_free(or_handshake_certs_t *certs)
+{
+ if (!certs)
+ return;
+
+ tor_x509_cert_free(certs->auth_cert);
+ tor_x509_cert_free(certs->id_cert);
+
+ memwipe(certs, 0xBD, sizeof(*certs));
+ tor_free(certs);
+}
diff --git a/src/or/torcert.h b/src/or/torcert.h
index 9c819c0..3f81fcd 100644
--- a/src/or/torcert.h
+++ b/src/or/torcert.h
@@ -72,5 +72,8 @@ ssize_t tor_make_rsa_ed25519_crosscert(const ed25519_public_key_t *ed_key,
time_t expires,
uint8_t **cert);
+or_handshake_certs_t *or_handshake_certs_new(void);
+void or_handshake_certs_free(or_handshake_certs_t *certs);
+
#endif
diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c
index 6c05670..3314880 100644
--- a/src/test/test_link_handshake.c
+++ b/src/test/test_link_handshake.c
@@ -147,8 +147,8 @@ test_link_handshake_certs_ok(void *arg)
channel_tls_process_certs_cell(cell2, chan1);
tt_assert(c1->handshake_state->received_certs_cell);
- tt_assert(c1->handshake_state->auth_cert == NULL);
- tt_assert(c1->handshake_state->id_cert);
+ tt_assert(c1->handshake_state->certs->auth_cert == NULL);
+ tt_assert(c1->handshake_state->certs->id_cert);
tt_assert(! tor_mem_is_zero(
(char*)c1->handshake_state->authenticated_peer_id, 20));
@@ -165,8 +165,8 @@ test_link_handshake_certs_ok(void *arg)
channel_tls_process_certs_cell(cell1, chan2);
tt_assert(c2->handshake_state->received_certs_cell);
- tt_assert(c2->handshake_state->auth_cert);
- tt_assert(c2->handshake_state->id_cert);
+ tt_assert(c2->handshake_state->certs->auth_cert);
+ tt_assert(c2->handshake_state->certs->id_cert);
tt_assert(tor_mem_is_zero(
(char*)c2->handshake_state->authenticated_peer_id, 20));
@@ -303,8 +303,8 @@ test_link_handshake_recv_certs_ok(void *arg)
tt_int_op(0, ==, mock_close_called);
tt_int_op(d->c->handshake_state->authenticated, ==, 1);
tt_int_op(d->c->handshake_state->received_certs_cell, ==, 1);
- tt_assert(d->c->handshake_state->id_cert != NULL);
- tt_assert(d->c->handshake_state->auth_cert == NULL);
+ tt_assert(d->c->handshake_state->certs->id_cert != NULL);
+ tt_assert(d->c->handshake_state->certs->auth_cert == NULL);
done:
;
@@ -324,8 +324,8 @@ test_link_handshake_recv_certs_ok_server(void *arg)
tt_int_op(0, ==, mock_close_called);
tt_int_op(d->c->handshake_state->authenticated, ==, 0);
tt_int_op(d->c->handshake_state->received_certs_cell, ==, 1);
- tt_assert(d->c->handshake_state->id_cert != NULL);
- tt_assert(d->c->handshake_state->auth_cert != NULL);
+ tt_assert(d->c->handshake_state->certs->id_cert != NULL);
+ tt_assert(d->c->handshake_state->certs->auth_cert != NULL);
done:
;
@@ -767,15 +767,15 @@ authenticate_data_setup(const struct testcase_t *test)
const uint8_t *der;
size_t sz;
tor_x509_cert_get_der(id_cert, &der, &sz);
- d->c1->handshake_state->id_cert = tor_x509_cert_decode(der, sz);
- d->c2->handshake_state->id_cert = tor_x509_cert_decode(der, sz);
+ d->c1->handshake_state->certs->id_cert = tor_x509_cert_decode(der, sz);
+ d->c2->handshake_state->certs->id_cert = tor_x509_cert_decode(der, sz);
tor_x509_cert_get_der(link_cert, &der, &sz);
mock_peer_cert = tor_x509_cert_decode(der, sz);
tt_assert(mock_peer_cert);
tt_assert(! tor_tls_get_my_certs(0, &auth_cert, &id_cert));
tor_x509_cert_get_der(auth_cert, &der, &sz);
- d->c2->handshake_state->auth_cert = tor_x509_cert_decode(der, sz);
+ d->c2->handshake_state->certs->auth_cert = tor_x509_cert_decode(der, sz);
/* Make an authenticate cell ... */
tt_int_op(0, ==, connection_or_send_authenticate_cell(d->c1,
@@ -825,7 +825,7 @@ test_link_handshake_auth_cell(void *arg)
uint8_t sig[128];
uint8_t digest[32];
- auth_pubkey = tor_tls_cert_get_key(d->c2->handshake_state->auth_cert);
+ auth_pubkey = tor_tls_cert_get_key(d->c2->handshake_state->certs->auth_cert);
int n = crypto_pk_public_checksig(
auth_pubkey,
(char*)sig, sizeof(sig), (char*)auth1_getarray_sig(auth1),
@@ -898,13 +898,13 @@ AUTHENTICATE_FAIL(nocerts,
AUTHENTICATE_FAIL(noidcert,
require_failure_message = "We never got an identity "
"certificate";
- tor_x509_cert_free(d->c2->handshake_state->id_cert);
- d->c2->handshake_state->id_cert = NULL)
+ tor_x509_cert_free(d->c2->handshake_state->certs->id_cert);
+ d->c2->handshake_state->certs->id_cert = NULL)
AUTHENTICATE_FAIL(noauthcert,
require_failure_message = "We never got an authentication "
"certificate";
- tor_x509_cert_free(d->c2->handshake_state->auth_cert);
- d->c2->handshake_state->auth_cert = NULL)
+ tor_x509_cert_free(d->c2->handshake_state->certs->auth_cert);
+ d->c2->handshake_state->certs->auth_cert = NULL)
AUTHENTICATE_FAIL(tooshort,
require_failure_message = "Cell was way too short";
d->cell->payload_len = 3)
1
0

03 Nov '16
commit 986695fb7497393ee8432592874bb1b88f5ae0cf
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu Mar 5 10:59:04 2015 +0100
When parsing certs cells, allow more certs types
Implements the parsing part of #19157
---
src/or/channeltls.c | 137 +++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 114 insertions(+), 23 deletions(-)
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index 9c2411e..e30ecb0 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -33,6 +33,7 @@
#include "router.h"
#include "routerlist.h"
#include "scheduler.h"
+#include "torcert.h"
/** How many CELL_PADDING cells have we received, ever? */
uint64_t stats_n_padding_cells_processed = 0;
@@ -1722,6 +1723,41 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
assert_connection_ok(TO_CONN(chan->conn),time(NULL));
}
+/** Types of certificates that we know how to parse from CERTS cells. Each
+ * type corresponds to a different encoding format. */
+typedef enum cert_encoding_t {
+ CERT_ENCODING_UNKNOWN, /**< We don't recognize this. */
+ CERT_ENCODING_X509, /**< It's an RSA key, signed with RSA, encoded in x509.
+ * (Actually, it might not be RSA. We test that later.) */
+ CERT_ENCODING_ED25519, /**< It's something signed with an Ed25519 key,
+ * encoded asa a tor_cert_t.*/
+ CERT_ENCODING_RSA_CROSSCERT, /**< It's an Ed key signed with an RSA key. */
+} cert_encoding_t;
+
+/**
+ * Given one of the certificate type codes used in a CERTS cell,
+ * return the corresponding cert_encoding_t that we should use to parse
+ * the certificate.
+ */
+static cert_encoding_t
+certs_cell_typenum_to_cert_type(int typenum)
+{
+ switch (typenum) {
+ case CERTTYPE_RSA1024_ID_LINK:
+ case CERTTYPE_RSA1024_ID_ID:
+ case CERTTYPE_RSA1024_ID_AUTH:
+ return CERT_ENCODING_X509;
+ case CERTTYPE_ED_ID_SIGN:
+ case CERTTYPE_ED_SIGN_LINK:
+ case CERTTYPE_ED_SIGN_AUTH:
+ return CERT_ENCODING_ED25519;
+ case CERTTYPE_RSA1024_ID_EDID:
+ return CERT_ENCODING_RSA_CROSSCERT;
+ default:
+ return CERT_ENCODING_UNKNOWN;
+ }
+}
+
/**
* Process a CERTS cell from a channel.
*
@@ -1741,14 +1777,20 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
STATIC void
channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
{
-#define MAX_CERT_TYPE_WANTED OR_CERT_TYPE_AUTH_1024
- tor_x509_cert_t *certs[MAX_CERT_TYPE_WANTED + 1];
+#define MAX_CERT_TYPE_WANTED CERTTYPE_RSA1024_ID_EDID
+ /* These arrays will be sparse, since a cert type can be at most one
+ * of ed/x509 */
+ tor_x509_cert_t *x509_certs[MAX_CERT_TYPE_WANTED + 1];
+ tor_cert_t *ed_certs[MAX_CERT_TYPE_WANTED + 1];
+
+ rsa_ed_crosscert_t *rsa_crosscert = NULL;
int n_certs, i;
certs_cell_t *cc = NULL;
int send_netinfo = 0;
- memset(certs, 0, sizeof(certs));
+ memset(x509_certs, 0, sizeof(x509_certs));
+ memset(ed_certs, 0, sizeof(ed_certs));
tor_assert(cell);
tor_assert(chan);
tor_assert(chan->conn);
@@ -1792,26 +1834,70 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
if (cert_type > MAX_CERT_TYPE_WANTED)
continue;
-
- tor_x509_cert_t *cert = tor_x509_cert_decode(cert_body, cert_len);
- if (!cert) {
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Received undecodable certificate in CERTS cell from %s:%d",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port);
- } else {
- if (certs[cert_type]) {
- tor_x509_cert_free(cert);
- ERR("Duplicate x509 certificate");
- } else {
- certs[cert_type] = cert;
+ const cert_encoding_t ct = certs_cell_typenum_to_cert_type(cert_type);
+ switch (ct) {
+ default:
+ case CERT_ENCODING_UNKNOWN:
+ break;
+ case CERT_ENCODING_X509: {
+ tor_x509_cert_t *x509_cert = tor_x509_cert_decode(cert_body, cert_len);
+ if (!x509_cert) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Received undecodable certificate in CERTS cell from %s:%d",
+ safe_str(chan->conn->base_.address),
+ chan->conn->base_.port);
+ } else {
+ if (x509_certs[cert_type]) {
+ tor_x509_cert_free(x509_cert);
+ ERR("Duplicate x509 certificate");
+ } else {
+ x509_certs[cert_type] = x509_cert;
+ }
+ }
+ break;
+ }
+ case CERT_ENCODING_ED25519: {
+ tor_cert_t *ed_cert = tor_cert_parse(cert_body, cert_len);
+ if (!ed_cert) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Received undecodable Ed certificate in CERTS cell from %s:%d",
+ safe_str(chan->conn->base_.address),
+ chan->conn->base_.port);
+ } else {
+ if (ed_certs[cert_type]) {
+ tor_cert_free(ed_cert);
+ ERR("Duplicate Ed25519 certificate");
+ } else {
+ ed_certs[cert_type] = ed_cert;
+ }
+ }
+ break;
+ }
+ case CERT_ENCODING_RSA_CROSSCERT: {
+ rsa_ed_crosscert_t *cc_cert = NULL;
+ ssize_t n = rsa_ed_crosscert_parse(&cc_cert, cert_body, cert_len);
+ if (n != cert_len) {
+ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
+ "Received unparseable RS1024-Ed25519 crosscert "
+ " in CERTS cell from %s:%d",
+ safe_str(chan->conn->base_.address),
+ chan->conn->base_.port);
+ } else {
+ if (rsa_crosscert) {
+ rsa_ed_crosscert_free(cc_cert);
+ ERR("Duplicate RSA->Ed25519 crosscert");
+ } else {
+ rsa_crosscert = cc_cert;
+ }
+ }
+ break;
}
}
}
- tor_x509_cert_t *id_cert = certs[OR_CERT_TYPE_ID_1024];
- tor_x509_cert_t *auth_cert = certs[OR_CERT_TYPE_AUTH_1024];
- tor_x509_cert_t *link_cert = certs[OR_CERT_TYPE_TLS_LINK];
+ tor_x509_cert_t *id_cert = x509_certs[OR_CERT_TYPE_ID_1024];
+ tor_x509_cert_t *auth_cert = x509_certs[OR_CERT_TYPE_AUTH_1024];
+ tor_x509_cert_t *link_cert = x509_certs[OR_CERT_TYPE_TLS_LINK];
if (chan->conn->handshake_state->started_here) {
int severity;
@@ -1862,7 +1948,7 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
safe_str(chan->conn->base_.address), chan->conn->base_.port);
chan->conn->handshake_state->id_cert = id_cert;
- certs[OR_CERT_TYPE_ID_1024] = NULL;
+ x509_certs[OR_CERT_TYPE_ID_1024] = NULL;
if (!public_server_mode(get_options())) {
/* If we initiated the connection and we are not a public server, we
@@ -1889,7 +1975,8 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
chan->conn->handshake_state->id_cert = id_cert;
chan->conn->handshake_state->auth_cert = auth_cert;
- certs[OR_CERT_TYPE_ID_1024] = certs[OR_CERT_TYPE_AUTH_1024] = NULL;
+ x509_certs[OR_CERT_TYPE_ID_1024] = x509_certs[OR_CERT_TYPE_AUTH_1024]
+ = NULL;
}
chan->conn->handshake_state->received_certs_cell = 1;
@@ -1903,9 +1990,13 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
}
err:
- for (unsigned u = 0; u < ARRAY_LENGTH(certs); ++u) {
- tor_x509_cert_free(certs[u]);
+ for (unsigned u = 0; u < ARRAY_LENGTH(x509_certs); ++u) {
+ tor_x509_cert_free(x509_certs[u]);
+ }
+ for (unsigned u = 0; u < ARRAY_LENGTH(ed_certs); ++u) {
+ tor_cert_free(ed_certs[u]);
}
+ rsa_ed_crosscert_free(rsa_crosscert);
certs_cell_free(cc);
#undef ERR
}
1
0

[tor/master] Refactor RSA certificate checking into its own function.
by nickm@torproject.org 03 Nov '16
by nickm@torproject.org 03 Nov '16
03 Nov '16
commit 348b90a915a5867bc0d8888e0fd12e8ec2319628
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu May 21 14:28:12 2015 -0400
Refactor RSA certificate checking into its own function.
---
src/or/channeltls.c | 61 +++++++++++++++++-------------------------
src/or/connection_or.c | 1 +
src/or/or.h | 4 +++
src/or/torcert.c | 47 ++++++++++++++++++++++++++++++++
src/or/torcert.h | 4 +++
src/test/test_link_handshake.c | 11 ++++++--
6 files changed, 89 insertions(+), 39 deletions(-)
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index fbe784c..cf57c29 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -1899,27 +1899,30 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
tor_x509_cert_t *auth_cert = x509_certs[OR_CERT_TYPE_AUTH_1024];
tor_x509_cert_t *link_cert = x509_certs[OR_CERT_TYPE_TLS_LINK];
+ chan->conn->handshake_state->certs->auth_cert = auth_cert;
+ chan->conn->handshake_state->certs->link_cert = link_cert;
+ chan->conn->handshake_state->certs->id_cert = id_cert;
+ x509_certs[OR_CERT_TYPE_ID_1024] =
+ x509_certs[OR_CERT_TYPE_AUTH_1024] =
+ x509_certs[OR_CERT_TYPE_TLS_LINK] = NULL;
+
+ int severity;
+ /* Note that this warns more loudly about time and validity if we were
+ * _trying_ to connect to an authority, not necessarily if we _did_ connect
+ * to one. */
+ if (chan->conn->handshake_state->started_here &&
+ router_digest_is_trusted_dir(TLS_CHAN_TO_BASE(chan)->identity_digest))
+ severity = LOG_WARN;
+ else
+ severity = LOG_PROTOCOL_WARN;
+
+ if (! or_handshake_certs_rsa_ok(severity,
+ chan->conn->handshake_state->certs,
+ chan->conn->tls))
+ ERR("Invalid RSA certificates!");
+
if (chan->conn->handshake_state->started_here) {
- int severity;
- if (! (id_cert && link_cert))
- ERR("The certs we wanted were missing");
- /* Okay. We should be able to check the certificates now. */
- if (! tor_tls_cert_matches_key(chan->conn->tls, link_cert)) {
- ERR("The link certificate didn't match the TLS public key");
- }
- /* Note that this warns more loudly about time and validity if we were
- * _trying_ to connect to an authority, not necessarily if we _did_ connect
- * to one. */
- if (router_digest_is_trusted_dir(
- TLS_CHAN_TO_BASE(chan)->identity_digest))
- severity = LOG_WARN;
- else
- severity = LOG_PROTOCOL_WARN;
-
- if (! tor_tls_cert_is_valid(severity, link_cert, id_cert, 0))
- ERR("The link certificate was not valid");
- if (! tor_tls_cert_is_valid(severity, id_cert, id_cert, 1))
- ERR("The ID certificate was not valid");
+ /* No more information is needed. */
chan->conn->handshake_state->authenticated = 1;
{
@@ -1947,9 +1950,6 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
"Got some good certificates from %s:%d: Authenticated it.",
safe_str(chan->conn->base_.address), chan->conn->base_.port);
- chan->conn->handshake_state->certs->id_cert = id_cert;
- x509_certs[OR_CERT_TYPE_ID_1024] = NULL;
-
if (!public_server_mode(get_options())) {
/* If we initiated the connection and we are not a public server, we
* aren't planning to authenticate at all. At this point we know who we
@@ -1957,26 +1957,13 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
send_netinfo = 1;
}
} else {
- if (! (id_cert && auth_cert))
- ERR("The certs we wanted were missing");
-
- /* Remember these certificates so we can check an AUTHENTICATE cell */
- if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, auth_cert, id_cert, 1))
- ERR("The authentication certificate was not valid");
- if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, id_cert, id_cert, 1))
- ERR("The ID certificate was not valid");
-
+ /* We can't call it authenticated till we see an AUTHENTICATE cell. */
log_info(LD_OR,
"Got some good certificates from %s:%d: "
"Waiting for AUTHENTICATE.",
safe_str(chan->conn->base_.address),
chan->conn->base_.port);
/* XXXX check more stuff? */
-
- chan->conn->handshake_state->certs->id_cert = id_cert;
- chan->conn->handshake_state->certs->auth_cert = auth_cert;
- x509_certs[OR_CERT_TYPE_ID_1024] = x509_certs[OR_CERT_TYPE_AUTH_1024]
- = NULL;
}
chan->conn->handshake_state->received_certs_cell = 1;
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 5a9c597..2591b40 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -1765,6 +1765,7 @@ connection_init_or_handshake_state(or_connection_t *conn, int started_here)
s->digest_sent_data = 1;
s->digest_received_data = 1;
s->certs = or_handshake_certs_new();
+ s->certs->started_here = s->started_here;
return 0;
}
diff --git a/src/or/or.h b/src/or/or.h
index cdde448..5feba28 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1387,8 +1387,12 @@ typedef struct listener_connection_t {
#define V3_AUTH_BODY_LEN (V3_AUTH_FIXED_PART_LEN + 8 + 16)
typedef struct or_handshake_certs_t {
+ /** DOCDOC */
+ int started_here;
/** The cert for the key that's supposed to sign the AUTHENTICATE cell */
tor_x509_cert_t *auth_cert;
+ /** DOCDOC */
+ tor_x509_cert_t *link_cert;
/** A self-signed identity certificate */
tor_x509_cert_t *id_cert;
/** DOCDOC */
diff --git a/src/or/torcert.c b/src/or/torcert.c
index e8bee54..2f0cc53 100644
--- a/src/or/torcert.c
+++ b/src/or/torcert.c
@@ -9,6 +9,7 @@
*/
#include "or.h"
+#include "config.h"
#include "crypto.h"
#include "torcert.h"
#include "ed25519_cert.h"
@@ -315,3 +316,49 @@ or_handshake_certs_free(or_handshake_certs_t *certs)
memwipe(certs, 0xBD, sizeof(*certs));
tor_free(certs);
}
+
+#define ERR(s) \
+ do { \
+ log_fn(severity, LD_PROTOCOL, \
+ "Received a bad CERTS cell: %s", \
+ (s)); \
+ return 0; \
+ } while (0)
+
+int
+or_handshake_certs_rsa_ok(int severity,
+ or_handshake_certs_t *certs,
+ tor_tls_t *tls)
+{
+ tor_x509_cert_t *link_cert = certs->link_cert;
+ tor_x509_cert_t *auth_cert = certs->auth_cert;
+ tor_x509_cert_t *id_cert = certs->id_cert;
+
+ if (certs->started_here) {
+ if (! (id_cert && link_cert))
+ ERR("The certs we wanted were missing");
+ if (! tor_tls_cert_matches_key(tls, link_cert))
+ ERR("The link certificate didn't match the TLS public key");
+ if (! tor_tls_cert_is_valid(severity, link_cert, id_cert, 0))
+ ERR("The link certificate was not valid");
+ if (! tor_tls_cert_is_valid(severity, id_cert, id_cert, 1))
+ ERR("The ID certificate was not valid");
+ } else {
+ if (! (id_cert && auth_cert))
+ ERR("The certs we wanted were missing");
+ /* Remember these certificates so we can check an AUTHENTICATE cell */
+ if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, auth_cert, id_cert, 1))
+ ERR("The authentication certificate was not valid");
+ if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, id_cert, id_cert, 1))
+ ERR("The ID certificate was not valid");
+ }
+
+ return 1;
+}
+
+int
+or_handshake_certs_ed25519_ok(or_handshake_certs_t *certs)
+{
+ (void) certs;
+ return 0;
+}
diff --git a/src/or/torcert.h b/src/or/torcert.h
index 3f81fcd..0420b41 100644
--- a/src/or/torcert.h
+++ b/src/or/torcert.h
@@ -74,6 +74,10 @@ ssize_t tor_make_rsa_ed25519_crosscert(const ed25519_public_key_t *ed_key,
or_handshake_certs_t *or_handshake_certs_new(void);
void or_handshake_certs_free(or_handshake_certs_t *certs);
+int or_handshake_certs_rsa_ok(int severity,
+ or_handshake_certs_t *certs,
+ tor_tls_t *tls);
+int or_handshake_certs_ed25519_ok(or_handshake_certs_t *certs);
#endif
diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c
index 3314880..91c6299 100644
--- a/src/test/test_link_handshake.c
+++ b/src/test/test_link_handshake.c
@@ -315,6 +315,7 @@ test_link_handshake_recv_certs_ok_server(void *arg)
{
certs_data_t *d = arg;
d->c->handshake_state->started_here = 0;
+ d->c->handshake_state->certs->started_here = 0;
certs_cell_get_certs(d->ccell, 0)->cert_type = 3;
certs_cell_get_certs(d->ccell, 1)->cert_type = 2;
ssize_t n = certs_cell_encode(d->cell->payload, 2048, d->ccell);
@@ -450,17 +451,21 @@ CERTS_FAIL(server_missing_certs,
{
require_failure_message = "The certs we wanted were missing";
d->c->handshake_state->started_here = 0;
+ d->c->handshake_state->certs->started_here = 0;
+
})
CERTS_FAIL(server_wrong_labels_1,
{
require_failure_message =
"The authentication certificate was not valid";
d->c->handshake_state->started_here = 0;
+ d->c->handshake_state->certs->started_here = 0;
certs_cell_get_certs(d->ccell, 0)->cert_type = 2;
certs_cell_get_certs(d->ccell, 1)->cert_type = 3;
REENCODE();
})
+
static void
test_link_handshake_send_authchallenge(void *arg)
{
@@ -637,7 +642,8 @@ AUTHCHALLENGE_FAIL(badproto,
AUTHCHALLENGE_FAIL(as_server,
require_failure_message = "We didn't originate this "
"connection";
- d->c->handshake_state->started_here = 0;)
+ d->c->handshake_state->started_here = 0;
+ d->c->handshake_state->certs->started_here = 0;)
AUTHCHALLENGE_FAIL(duplicate,
require_failure_message = "We already received one";
d->c->handshake_state->received_auth_challenge = 1)
@@ -874,7 +880,8 @@ AUTHENTICATE_FAIL(badproto,
d->c2->link_proto = 2)
AUTHENTICATE_FAIL(atclient,
require_failure_message = "We originated this connection";
- d->c2->handshake_state->started_here = 1)
+ d->c2->handshake_state->started_here = 1;
+ d->c2->handshake_state->certs->started_here = 1;)
AUTHENTICATE_FAIL(duplicate,
require_failure_message = "We already got one";
d->c2->handshake_state->received_authenticate = 1)
1
0

03 Nov '16
commit e64bac6eb4a89ae63a2d5c1cb41cac903f1e8e66
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Aug 30 11:04:44 2016 -0400
Increase TLS RSA link key length to 2048 bits
Oddly, nothing broke.
Closes ticket 13752.
---
changes/feature13752 | 4 ++++
src/common/tortls.c | 8 +++++---
src/test/test_link_handshake.c | 3 ++-
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/changes/feature13752 b/changes/feature13752
new file mode 100644
index 0000000..f318cc2
--- /dev/null
+++ b/changes/feature13752
@@ -0,0 +1,4 @@
+ o Minor features (fingerprinting resistence, authentication):
+ - Extend the length of RSA keys used for TLS link authentication to
+ 2048 bits. (These weren't used for forward secrecy; for forward
+ secrecy, we used P256.) Closes ticket 13752.
diff --git a/src/common/tortls.c b/src/common/tortls.c
index fd86981..33bd334 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -775,8 +775,8 @@ tor_tls_context_decref(tor_tls_context_t *ctx)
/** Set *<b>link_cert_out</b> and *<b>id_cert_out</b> to the link certificate
* and ID certificate that we're currently using for our V3 in-protocol
* handshake's certificate chain. If <b>server</b> is true, provide the certs
- * that we use in server mode; otherwise, provide the certs that we use in
- * client mode. */
+ * that we use in server mode (auth, ID); otherwise, provide the certs that we
+ * use in client mode. (link, ID) */
int
tor_tls_get_my_certs(int server,
const tor_x509_cert_t **link_cert_out,
@@ -1026,6 +1026,8 @@ tor_tls_context_init_one(tor_tls_context_t **ppcontext,
/** The group we should use for ecdhe when none was selected. */
#define NID_tor_default_ecdhe_group NID_X9_62_prime256v1
+#define RSA_LINK_KEY_BITS 2048
+
/** 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.
@@ -1051,7 +1053,7 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
/* Generate short-term RSA key for use with TLS. */
if (!(rsa = crypto_pk_new()))
goto error;
- if (crypto_pk_generate_key(rsa)<0)
+ if (crypto_pk_generate_key_with_bits(rsa, RSA_LINK_KEY_BITS)<0)
goto error;
if (!is_client) {
/* Generate short-term RSA key for use in the in-protocol ("v3")
diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c
index 9a3b57d..05c8400 100644
--- a/src/test/test_link_handshake.c
+++ b/src/test/test_link_handshake.c
@@ -258,7 +258,8 @@ recv_certs_setup(const struct testcase_t *test)
const tor_x509_cert_t *a,*b;
const uint8_t *enca, *encb;
size_t lena, lenb;
- tor_tls_get_my_certs(1, &a, &b);
+ tor_tls_get_my_certs(0, &a, &b); /* Use '0' here to make sure we get
+ * auth cert */
tor_x509_cert_get_der(a, &enca, &lena);
tor_x509_cert_get_der(b, &encb, &lenb);
certs_cell_cert_setlen_body(ccc1, lena);
1
0

[tor/master] Add "Ed ID" arguments to a bunch of connection-ID-related fns.
by nickm@torproject.org 03 Nov '16
by nickm@torproject.org 03 Nov '16
03 Nov '16
commit 99b3e54691f451b766556391cba6e26120ad7d84
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Aug 30 09:44:42 2016 -0400
Add "Ed ID" arguments to a bunch of connection-ID-related fns.
In particular, these functions are the ones that set the identity of
a given connection or channel, and/or confirm that we have learned
said IDs.
There's a lot of stub code here: we don't actually need to use the
new keys till we start looking up connections/channels by Ed25519
IDs. Still, we want to start passing the Ed25519 IDs in now, so it
makes sense to add these stubs as part of 15055.
---
src/or/channel.c | 5 ++--
src/or/channel.h | 3 ++-
src/or/channeltls.c | 26 ++++++++++++++------
src/or/channeltls.h | 3 ++-
src/or/circuitbuild.c | 5 +++-
src/or/connection_or.c | 56 +++++++++++++++++++++++++++---------------
src/or/connection_or.h | 10 +++++---
src/or/dirserv.c | 8 ++++--
src/or/or.h | 9 +++++--
src/test/test_channeltls.c | 9 ++++---
src/test/test_link_handshake.c | 4 +--
11 files changed, 93 insertions(+), 45 deletions(-)
diff --git a/src/or/channel.c b/src/or/channel.c
index 6a78b21..a9487b4 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -3223,9 +3223,10 @@ channel_free_all(void)
channel_t *
channel_connect(const tor_addr_t *addr, uint16_t port,
- const char *id_digest)
+ const char *id_digest,
+ const ed25519_public_key_t *ed_id)
{
- return channel_tls_connect(addr, port, id_digest);
+ return channel_tls_connect(addr, port, id_digest, ed_id);
}
/**
diff --git a/src/or/channel.h b/src/or/channel.h
index a711b56..7b8b311 100644
--- a/src/or/channel.h
+++ b/src/or/channel.h
@@ -486,7 +486,8 @@ int channel_send_destroy(circid_t circ_id, channel_t *chan,
*/
channel_t * channel_connect(const tor_addr_t *addr, uint16_t port,
- const char *id_digest);
+ const char *id_digest,
+ const ed25519_public_key_t *ed_id);
channel_t * channel_get_for_extend(const char *digest,
const tor_addr_t *target_addr,
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index 9315f80..d1fae92 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -149,8 +149,10 @@ channel_tls_common_init(channel_tls_t *tlschan)
channel_t *
channel_tls_connect(const tor_addr_t *addr, uint16_t port,
- const char *id_digest)
+ const char *id_digest,
+ const ed25519_public_key_t *ed_id)
{
+ (void) ed_id; // XXXX not fully used yet
channel_tls_t *tlschan = tor_malloc_zero(sizeof(*tlschan));
channel_t *chan = &(tlschan->base_);
@@ -177,7 +179,7 @@ channel_tls_connect(const tor_addr_t *addr, uint16_t port,
channel_mark_outgoing(chan);
/* Set up or_connection stuff */
- tlschan->conn = connection_or_connect(addr, port, id_digest, tlschan);
+ tlschan->conn = connection_or_connect(addr, port, id_digest, ed_id, tlschan);
/* connection_or_connect() will fill in tlschan->conn */
if (!(tlschan->conn)) {
chan->reason_for_closing = CHANNEL_CLOSE_FOR_ERROR;
@@ -1618,7 +1620,10 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
if (!(chan->conn->handshake_state->authenticated)) {
tor_assert(tor_digest_is_zero(
(const char*)(chan->conn->handshake_state->
- authenticated_peer_id)));
+ authenticated_rsa_peer_id)));
+ tor_assert(tor_mem_is_zero(
+ (const char*)(chan->conn->handshake_state->
+ authenticated_ed25519_peer_id.pubkey), 32));
channel_set_circid_type(TLS_CHAN_TO_BASE(chan), NULL,
chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS);
@@ -1626,7 +1631,8 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan)
&(chan->conn->base_.addr),
chan->conn->base_.port,
(const char*)(chan->conn->handshake_state->
- authenticated_peer_id),
+ authenticated_rsa_peer_id),
+ NULL, // XXXX Ed key
0);
}
}
@@ -1926,6 +1932,7 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
/* No more information is needed. */
chan->conn->handshake_state->authenticated = 1;
+ chan->conn->handshake_state->authenticated_rsa = 1;
{
const common_digests_t *id_digests =
tor_x509_cert_get_id_digests(id_cert);
@@ -1936,7 +1943,7 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
identity_rcvd = tor_tls_cert_get_key(id_cert);
if (!identity_rcvd)
ERR("Internal error: Couldn't get RSA key from ID cert.");
- memcpy(chan->conn->handshake_state->authenticated_peer_id,
+ memcpy(chan->conn->handshake_state->authenticated_rsa_peer_id,
id_digests->d[DIGEST_SHA1], DIGEST_LEN);
channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd,
chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS);
@@ -1944,7 +1951,8 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
}
if (connection_or_client_learned_peer_id(chan->conn,
- chan->conn->handshake_state->authenticated_peer_id) < 0)
+ chan->conn->handshake_state->authenticated_rsa_peer_id,
+ NULL) < 0)
ERR("Problem setting or checking peer id");
log_info(LD_OR,
@@ -2219,6 +2227,7 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
/* Okay, we are authenticated. */
chan->conn->handshake_state->received_authenticate = 1;
chan->conn->handshake_state->authenticated = 1;
+ chan->conn->handshake_state->authenticated_rsa = 1;
chan->conn->handshake_state->digest_received_data = 0;
{
crypto_pk_t *identity_rcvd =
@@ -2229,7 +2238,7 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
/* This must exist; we checked key type when reading the cert. */
tor_assert(id_digests);
- memcpy(chan->conn->handshake_state->authenticated_peer_id,
+ memcpy(chan->conn->handshake_state->authenticated_rsa_peer_id,
id_digests->d[DIGEST_SHA1], DIGEST_LEN);
channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd,
@@ -2240,7 +2249,8 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
&(chan->conn->base_.addr),
chan->conn->base_.port,
(const char*)(chan->conn->handshake_state->
- authenticated_peer_id),
+ authenticated_rsa_peer_id),
+ NULL, // XXXX Ed key
0);
log_info(LD_OR,
diff --git a/src/or/channeltls.h b/src/or/channeltls.h
index 8b5863a..729e595 100644
--- a/src/or/channeltls.h
+++ b/src/or/channeltls.h
@@ -29,7 +29,8 @@ struct channel_tls_s {
#endif /* TOR_CHANNEL_INTERNAL_ */
channel_t * channel_tls_connect(const tor_addr_t *addr, uint16_t port,
- const char *id_digest);
+ const char *id_digest,
+ const ed25519_public_key_t *ed_id);
channel_listener_t * channel_tls_get_listener(void);
channel_listener_t * channel_tls_start_listener(void);
channel_t * channel_tls_handle_incoming(or_connection_t *orconn);
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 12c7553..74a947b 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -69,7 +69,10 @@ channel_connect_for_circuit(const tor_addr_t *addr, uint16_t port,
{
channel_t *chan;
- chan = channel_connect(addr, port, id_digest);
+
+ chan = channel_connect(addr, port, id_digest,
+ NULL // XXXX Ed25519 id.
+ );
if (chan) command_setup_channel(chan);
return chan;
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 2591b40..9048fde 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -134,15 +134,18 @@ connection_or_clear_identity_map(void)
/** Change conn->identity_digest to digest, and add conn into
* orconn_digest_map. */
static void
-connection_or_set_identity_digest(or_connection_t *conn, const char *digest)
+connection_or_set_identity_digest(or_connection_t *conn,
+ const char *rsa_digest,
+ const ed25519_public_key_t *ed_id)
{
+ (void) ed_id; // DOCDOC // XXXX not implemented yet.
or_connection_t *tmp;
tor_assert(conn);
- tor_assert(digest);
+ tor_assert(rsa_digest);
if (!orconn_identity_map)
orconn_identity_map = digestmap_new();
- if (tor_memeq(conn->identity_digest, digest, DIGEST_LEN))
+ if (tor_memeq(conn->identity_digest, rsa_digest, DIGEST_LEN))
return;
/* If the identity was set previously, remove the old mapping. */
@@ -152,23 +155,23 @@ connection_or_set_identity_digest(or_connection_t *conn, const char *digest)
channel_clear_identity_digest(TLS_CHAN_TO_BASE(conn->chan));
}
- memcpy(conn->identity_digest, digest, DIGEST_LEN);
+ memcpy(conn->identity_digest, rsa_digest, DIGEST_LEN);
/* If we're setting the ID to zero, don't add a mapping. */
- if (tor_digest_is_zero(digest))
+ if (tor_digest_is_zero(rsa_digest))
return;
- tmp = digestmap_set(orconn_identity_map, digest, conn);
+ tmp = digestmap_set(orconn_identity_map, rsa_digest, conn);
conn->next_with_same_id = tmp;
/* Deal with channels */
if (conn->chan)
- channel_set_identity_digest(TLS_CHAN_TO_BASE(conn->chan), digest);
+ channel_set_identity_digest(TLS_CHAN_TO_BASE(conn->chan), rsa_digest);
#if 1
/* Testing code to check for bugs in representation. */
for (; tmp; tmp = tmp->next_with_same_id) {
- tor_assert(tor_memeq(tmp->identity_digest, digest, DIGEST_LEN));
+ tor_assert(tor_memeq(tmp->identity_digest, rsa_digest, DIGEST_LEN));
tor_assert(tmp != conn);
}
#endif
@@ -866,10 +869,12 @@ void
connection_or_init_conn_from_address(or_connection_t *conn,
const tor_addr_t *addr, uint16_t port,
const char *id_digest,
+ const ed25519_public_key_t *ed_id,
int started_here)
{
+ (void) ed_id; // not fully used yet.
const node_t *r = node_get_by_id(id_digest);
- connection_or_set_identity_digest(conn, id_digest);
+ connection_or_set_identity_digest(conn, id_digest, ed_id);
connection_or_update_token_buckets_helper(conn, 1, get_options());
conn->base_.port = port;
@@ -1162,8 +1167,11 @@ connection_or_notify_error(or_connection_t *conn,
MOCK_IMPL(or_connection_t *,
connection_or_connect, (const tor_addr_t *_addr, uint16_t port,
- const char *id_digest, channel_tls_t *chan))
+ const char *id_digest,
+ const ed25519_public_key_t *ed_id,
+ channel_tls_t *chan))
{
+ (void) ed_id; // XXXX not fully used yet.
or_connection_t *conn;
const or_options_t *options = get_options();
int socket_error = 0;
@@ -1194,7 +1202,7 @@ connection_or_connect, (const tor_addr_t *_addr, uint16_t port,
*/
conn->chan = chan;
chan->conn = conn;
- connection_or_init_conn_from_address(conn, &addr, port, id_digest, 1);
+ connection_or_init_conn_from_address(conn, &addr, port, id_digest, ed_id, 1);
connection_or_change_state(conn, OR_CONN_STATE_CONNECTING);
control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED, 0);
@@ -1553,7 +1561,9 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
if (started_here)
return connection_or_client_learned_peer_id(conn,
- (const uint8_t*)digest_rcvd_out);
+ (const uint8_t*)digest_rcvd_out,
+ NULL // Ed25519 ID
+ );
return 0;
}
@@ -1583,12 +1593,16 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
*/
int
connection_or_client_learned_peer_id(or_connection_t *conn,
- const uint8_t *peer_id)
+ const uint8_t *rsa_peer_id,
+ const ed25519_public_key_t *ed_peer_id)
{
+ (void) ed_peer_id; // not used yet.
+
const or_options_t *options = get_options();
if (tor_digest_is_zero(conn->identity_digest)) {
- connection_or_set_identity_digest(conn, (const char*)peer_id);
+ connection_or_set_identity_digest(conn,
+ (const char*)rsa_peer_id, ed_peer_id);
tor_free(conn->nickname);
conn->nickname = tor_malloc(HEX_DIGEST_LEN+2);
conn->nickname[0] = '$';
@@ -1600,14 +1614,14 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
/* if it's a bridge and we didn't know its identity fingerprint, now
* we do -- remember it for future attempts. */
learned_router_identity(&conn->base_.addr, conn->base_.port,
- (const char*)peer_id);
+ (const char*)rsa_peer_id /*, ed_peer_id XXXX */);
}
- if (tor_memneq(peer_id, conn->identity_digest, DIGEST_LEN)) {
+ if (tor_memneq(rsa_peer_id, conn->identity_digest, DIGEST_LEN)) {
/* I was aiming for a particular digest. I didn't get it! */
char seen[HEX_DIGEST_LEN+1];
char expected[HEX_DIGEST_LEN+1];
- base16_encode(seen, sizeof(seen), (const char*)peer_id, DIGEST_LEN);
+ base16_encode(seen, sizeof(seen), (const char*)rsa_peer_id, DIGEST_LEN);
base16_encode(expected, sizeof(expected), conn->identity_digest,
DIGEST_LEN);
const int using_hardcoded_fingerprints =
@@ -1660,7 +1674,7 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
}
if (authdir_mode_tests_reachability(options)) {
dirserv_orconn_tls_done(&conn->base_.addr, conn->base_.port,
- (const char*)peer_id);
+ (const char*)rsa_peer_id /*, ed_id XXXX */);
}
return 0;
@@ -1716,7 +1730,8 @@ connection_tls_finish_handshake(or_connection_t *conn)
if (tor_tls_used_v1_handshake(conn->tls)) {
conn->link_proto = 1;
connection_or_init_conn_from_address(conn, &conn->base_.addr,
- conn->base_.port, digest_rcvd, 0);
+ conn->base_.port, digest_rcvd,
+ NULL, 0);
tor_tls_block_renegotiation(conn->tls);
rep_hist_note_negotiated_link_proto(1, started_here);
return connection_or_set_state_open(conn);
@@ -1725,7 +1740,8 @@ connection_tls_finish_handshake(or_connection_t *conn)
if (connection_init_or_handshake_state(conn, started_here) < 0)
return -1;
connection_or_init_conn_from_address(conn, &conn->base_.addr,
- conn->base_.port, digest_rcvd, 0);
+ conn->base_.port, digest_rcvd,
+ NULL, 0);
return connection_or_send_versions(conn, 0);
}
}
diff --git a/src/or/connection_or.h b/src/or/connection_or.h
index 65a8ac1..7fdfbb0 100644
--- a/src/or/connection_or.h
+++ b/src/or/connection_or.h
@@ -40,7 +40,9 @@ void connection_or_notify_error(or_connection_t *conn,
MOCK_DECL(or_connection_t *,
connection_or_connect,
(const tor_addr_t *addr, uint16_t port,
- const char *id_digest, channel_tls_t *chan));
+ const char *id_digest,
+ const ed25519_public_key_t *ed_id,
+ channel_tls_t *chan));
void connection_or_close_normally(or_connection_t *orconn, int flush);
MOCK_DECL(void,connection_or_close_for_error,
@@ -59,10 +61,12 @@ int connection_init_or_handshake_state(or_connection_t *conn,
void connection_or_init_conn_from_address(or_connection_t *conn,
const tor_addr_t *addr,
uint16_t port,
- const char *id_digest,
+ const char *rsa_id_digest,
+ const ed25519_public_key_t *ed_id,
int started_here);
int connection_or_client_learned_peer_id(or_connection_t *conn,
- const uint8_t *peer_id);
+ const uint8_t *rsa_peer_id,
+ const ed25519_public_key_t *ed_peer_id);
time_t connection_or_client_used(or_connection_t *conn);
MOCK_DECL(int, connection_or_get_num_circuits, (or_connection_t *conn));
void or_handshake_state_free(or_handshake_state_t *state);
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index ff50ca4..803e1aa 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -3199,7 +3199,9 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router)
router->nickname, fmt_addr32(router->addr), router->or_port);
tor_addr_from_ipv4h(&router_addr, router->addr);
chan = channel_tls_connect(&router_addr, router->or_port,
- router->cache_info.identity_digest);
+ router->cache_info.identity_digest,
+ NULL // XXXX Ed25519 ID.
+ );
if (chan) command_setup_channel(chan);
/* Possible IPv6. */
@@ -3211,7 +3213,9 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router)
tor_addr_to_str(addrstr, &router->ipv6_addr, sizeof(addrstr), 1),
router->ipv6_orport);
chan = channel_tls_connect(&router->ipv6_addr, router->ipv6_orport,
- router->cache_info.identity_digest);
+ router->cache_info.identity_digest,
+ NULL // XXXX Ed25519 ID.
+ );
if (chan) command_setup_channel(chan);
}
}
diff --git a/src/or/or.h b/src/or/or.h
index 5feba28..65d4057 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1419,6 +1419,8 @@ typedef struct or_handshake_state_t {
/* True iff we've received valid authentication to some identity. */
unsigned int authenticated : 1;
+ unsigned int authenticated_rsa : 1;
+ unsigned int authenticated_ed25519 : 1;
/* True iff we have sent a netinfo cell */
unsigned int sent_netinfo : 1;
@@ -1436,9 +1438,12 @@ typedef struct or_handshake_state_t {
unsigned int digest_received_data : 1;
/**@}*/
- /** Identity digest that we have received and authenticated for our peer
+ /** Identity RSA digest that we have received and authenticated for our peer
* on this connection. */
- uint8_t authenticated_peer_id[DIGEST_LEN];
+ uint8_t authenticated_rsa_peer_id[DIGEST_LEN];
+ /** Identity Ed25519 public key that we have received and authenticated for
+ * our peer on this connection. */
+ ed25519_public_key_t authenticated_ed25519_peer_id;
/** Digests of the cells that we have sent or received as part of a V3
* handshake. Used for making and checking AUTHENTICATE cells.
diff --git a/src/test/test_channeltls.c b/src/test/test_channeltls.c
index bde46a2..36ae4d1 100644
--- a/src/test/test_channeltls.c
+++ b/src/test/test_channeltls.c
@@ -30,6 +30,7 @@ static or_connection_t * tlschan_connection_or_connect_mock(
const tor_addr_t *addr,
uint16_t port,
const char *digest,
+ const ed25519_public_key_t *ed_id,
channel_tls_t *tlschan);
static int tlschan_is_local_addr_mock(const tor_addr_t *addr);
@@ -68,7 +69,7 @@ test_channeltls_create(void *arg)
MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
/* Try connecting */
- ch = channel_tls_connect(&test_addr, 567, test_digest);
+ ch = channel_tls_connect(&test_addr, 567, test_digest, NULL);
tt_assert(ch != NULL);
done:
@@ -117,7 +118,7 @@ test_channeltls_num_bytes_queued(void *arg)
MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
/* Try connecting */
- ch = channel_tls_connect(&test_addr, 567, test_digest);
+ ch = channel_tls_connect(&test_addr, 567, test_digest, NULL);
tt_assert(ch != NULL);
/*
@@ -202,7 +203,7 @@ test_channeltls_overhead_estimate(void *arg)
MOCK(connection_or_connect, tlschan_connection_or_connect_mock);
/* Try connecting */
- ch = channel_tls_connect(&test_addr, 567, test_digest);
+ ch = channel_tls_connect(&test_addr, 567, test_digest, NULL);
tt_assert(ch != NULL);
/* First case: silly low ratios should get clamped to 1.0 */
@@ -264,9 +265,11 @@ static or_connection_t *
tlschan_connection_or_connect_mock(const tor_addr_t *addr,
uint16_t port,
const char *digest,
+ const ed25519_public_key_t *ed_id,
channel_tls_t *tlschan)
{
or_connection_t *result = NULL;
+ (void) ed_id; // XXXX Not yet used.
tt_assert(addr != NULL);
tt_assert(port != 0);
diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c
index 91c6299..9a3b57d 100644
--- a/src/test/test_link_handshake.c
+++ b/src/test/test_link_handshake.c
@@ -150,7 +150,7 @@ test_link_handshake_certs_ok(void *arg)
tt_assert(c1->handshake_state->certs->auth_cert == NULL);
tt_assert(c1->handshake_state->certs->id_cert);
tt_assert(! tor_mem_is_zero(
- (char*)c1->handshake_state->authenticated_peer_id, 20));
+ (char*)c1->handshake_state->authenticated_rsa_peer_id, 20));
chan2 = tor_malloc_zero(sizeof(*chan2));
channel_tls_common_init(chan2);
@@ -168,7 +168,7 @@ test_link_handshake_certs_ok(void *arg)
tt_assert(c2->handshake_state->certs->auth_cert);
tt_assert(c2->handshake_state->certs->id_cert);
tt_assert(tor_mem_is_zero(
- (char*)c2->handshake_state->authenticated_peer_id, 20));
+ (char*)c2->handshake_state->authenticated_rsa_peer_id, 20));
done:
UNMOCK(tor_tls_cert_matches_key);
1
0

03 Nov '16
commit b4a5c779014b35d60f4a2ddcec31e7075ad52995
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Jun 19 09:09:49 2015 -0400
Verify ed25519 link handshake certificates
This code stores the ed certs as appropriate, and tries to check
them. The Ed25519 result is not yet used, and (because of its
behavior) this will break RSA authenticate cells. That will get
fixed as we go, however.
This should implement 19157, but it needs tests, and it needs
to get wired in.
---
src/or/channeltls.c | 90 ++++++++++++++++++-----------
src/or/connection_or.c | 10 +++-
src/or/or.h | 27 +++++++--
src/or/torcert.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++--
src/or/torcert.h | 10 ++++
5 files changed, 240 insertions(+), 47 deletions(-)
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index d1fae92..6de3bd4 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -1788,8 +1788,9 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
* of ed/x509 */
tor_x509_cert_t *x509_certs[MAX_CERT_TYPE_WANTED + 1];
tor_cert_t *ed_certs[MAX_CERT_TYPE_WANTED + 1];
+ uint8_t *rsa_ed_cc_cert = NULL;
+ size_t rsa_ed_cc_cert_len = 0;
- rsa_ed_crosscert_t *rsa_crosscert = NULL;
int n_certs, i;
certs_cell_t *cc = NULL;
@@ -1879,38 +1880,45 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
}
break;
}
+
case CERT_ENCODING_RSA_CROSSCERT: {
- rsa_ed_crosscert_t *cc_cert = NULL;
- ssize_t n = rsa_ed_crosscert_parse(&cc_cert, cert_body, cert_len);
- if (n != cert_len) {
- log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
- "Received unparseable RS1024-Ed25519 crosscert "
- " in CERTS cell from %s:%d",
- safe_str(chan->conn->base_.address),
- chan->conn->base_.port);
+ if (rsa_ed_cc_cert) {
+ ERR("Duplicate RSA->Ed25519 crosscert");
} else {
- if (rsa_crosscert) {
- rsa_ed_crosscert_free(cc_cert);
- ERR("Duplicate RSA->Ed25519 crosscert");
- } else {
- rsa_crosscert = cc_cert;
- }
+ rsa_ed_cc_cert = tor_memdup(cert_body, cert_len);
+ rsa_ed_cc_cert_len = cert_len;
}
break;
}
}
}
- tor_x509_cert_t *id_cert = x509_certs[OR_CERT_TYPE_ID_1024];
- tor_x509_cert_t *auth_cert = x509_certs[OR_CERT_TYPE_AUTH_1024];
- tor_x509_cert_t *link_cert = x509_certs[OR_CERT_TYPE_TLS_LINK];
-
+ /* Move the certificates we (might) want into the handshake_state->certs
+ * structure. */
+ tor_x509_cert_t *id_cert = x509_certs[CERTTYPE_RSA1024_ID_ID];
+ tor_x509_cert_t *auth_cert = x509_certs[CERTTYPE_RSA1024_ID_AUTH];
+ tor_x509_cert_t *link_cert = x509_certs[CERTTYPE_RSA1024_ID_LINK];
chan->conn->handshake_state->certs->auth_cert = auth_cert;
chan->conn->handshake_state->certs->link_cert = link_cert;
chan->conn->handshake_state->certs->id_cert = id_cert;
- x509_certs[OR_CERT_TYPE_ID_1024] =
- x509_certs[OR_CERT_TYPE_AUTH_1024] =
- x509_certs[OR_CERT_TYPE_TLS_LINK] = NULL;
+ x509_certs[CERTTYPE_RSA1024_ID_ID] =
+ x509_certs[CERTTYPE_RSA1024_ID_AUTH] =
+ x509_certs[CERTTYPE_RSA1024_ID_LINK] = NULL;
+
+ tor_cert_t *ed_id_sign = ed_certs[CERTTYPE_ED_ID_SIGN];
+ tor_cert_t *ed_sign_link = ed_certs[CERTTYPE_ED_SIGN_LINK];
+ tor_cert_t *ed_sign_auth = ed_certs[CERTTYPE_ED_SIGN_AUTH];
+ chan->conn->handshake_state->certs->ed_id_sign = ed_id_sign;
+ chan->conn->handshake_state->certs->ed_sign_link = ed_sign_link;
+ chan->conn->handshake_state->certs->ed_sign_auth = ed_sign_auth;
+ ed_certs[CERTTYPE_ED_ID_SIGN] =
+ ed_certs[CERTTYPE_ED_SIGN_LINK] =
+ ed_certs[CERTTYPE_ED_SIGN_AUTH] = NULL;
+
+ chan->conn->handshake_state->certs->ed_rsa_crosscert = rsa_ed_cc_cert;
+ chan->conn->handshake_state->certs->ed_rsa_crosscert_len =
+ rsa_ed_cc_cert_len;
+ rsa_ed_cc_cert = NULL;
int severity;
/* Note that this warns more loudly about time and validity if we were
@@ -1922,11 +1930,17 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
else
severity = LOG_PROTOCOL_WARN;
- if (! or_handshake_certs_rsa_ok(severity,
- chan->conn->handshake_state->certs,
- chan->conn->tls,
- time(NULL)))
- ERR("Invalid RSA certificates!");
+ const ed25519_public_key_t *checked_ed_id = NULL;
+ const common_digests_t *checked_rsa_id = NULL;
+ or_handshake_certs_check_both(severity,
+ chan->conn->handshake_state->certs,
+ chan->conn->tls,
+ time(NULL),
+ &checked_ed_id,
+ &checked_rsa_id);
+
+ if (!checked_rsa_id)
+ ERR("Invalid certificate chain!");
if (chan->conn->handshake_state->started_here) {
/* No more information is needed. */
@@ -1934,8 +1948,7 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
chan->conn->handshake_state->authenticated = 1;
chan->conn->handshake_state->authenticated_rsa = 1;
{
- const common_digests_t *id_digests =
- tor_x509_cert_get_id_digests(id_cert);
+ const common_digests_t *id_digests = checked_rsa_id;
crypto_pk_t *identity_rcvd;
if (!id_digests)
ERR("Couldn't compute digests for key in ID cert");
@@ -1950,14 +1963,22 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
crypto_pk_free(identity_rcvd);
}
+ if (checked_ed_id) {
+ chan->conn->handshake_state->authenticated_ed25519 = 1;
+ memcpy(&chan->conn->handshake_state->authenticated_ed25519_peer_id,
+ checked_ed_id, sizeof(ed25519_public_key_t));
+ }
+
if (connection_or_client_learned_peer_id(chan->conn,
chan->conn->handshake_state->authenticated_rsa_peer_id,
- NULL) < 0)
+ checked_ed_id) < 0)
ERR("Problem setting or checking peer id");
log_info(LD_OR,
- "Got some good certificates from %s:%d: Authenticated it.",
- safe_str(chan->conn->base_.address), chan->conn->base_.port);
+ "Got some good certificates from %s:%d: Authenticated it with "
+ "RSA%s",
+ safe_str(chan->conn->base_.address), chan->conn->base_.port,
+ checked_ed_id ? " and Ed25519" : "");
if (!public_server_mode(get_options())) {
/* If we initiated the connection and we are not a public server, we
@@ -1968,8 +1989,9 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
} else {
/* We can't call it authenticated till we see an AUTHENTICATE cell. */
log_info(LD_OR,
- "Got some good certificates from %s:%d: "
+ "Got some good RSA%s certificates from %s:%d. "
"Waiting for AUTHENTICATE.",
+ checked_ed_id ? " and Ed25519" : "",
safe_str(chan->conn->base_.address),
chan->conn->base_.port);
/* XXXX check more stuff? */
@@ -1992,7 +2014,7 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
for (unsigned u = 0; u < ARRAY_LENGTH(ed_certs); ++u) {
tor_cert_free(ed_certs[u]);
}
- rsa_ed_crosscert_free(rsa_crosscert);
+ tor_free(rsa_ed_cc_cert);
certs_cell_free(cc);
#undef ERR
}
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 9048fde..b922e97 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -2391,10 +2391,12 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
if (is_ed) {
const ed25519_public_key_t *my_ed_id, *their_ed_id;
- if (!conn->handshake_state->certs->ed_id_sign_cert)
+ if (!conn->handshake_state->certs->ed_id_sign) {
+ log_warn(LD_OR, "Ed authenticate without Ed ID cert from peer.");
goto err;
+ }
my_ed_id = get_master_identity_key();
- their_ed_id = &conn->handshake_state->certs->ed_id_sign_cert->signing_key;
+ their_ed_id = &conn->handshake_state->certs->ed_id_sign->signing_key;
const uint8_t *cid_ed = (server ? their_ed_id : my_ed_id)->pubkey;
const uint8_t *sid_ed = (server ? my_ed_id : their_ed_id)->pubkey;
@@ -2500,8 +2502,10 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
if (ed_signing_key && is_ed) {
ed25519_signature_t sig;
- if (ed25519_sign(&sig, out, len, ed_signing_key) < 0)
+ if (ed25519_sign(&sig, out, len, ed_signing_key) < 0) {
+ log_warn(LD_OR, "Unable to sign ed25519 cert");
goto err;
+ }
auth1_setlen_sig(auth, ED25519_SIG_LEN);
memcpy(auth1_getarray_sig(auth), sig.sig, ED25519_SIG_LEN);
diff --git a/src/or/or.h b/src/or/or.h
index 65d4057..e6162c5 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1386,17 +1386,32 @@ typedef struct listener_connection_t {
* signs. */
#define V3_AUTH_BODY_LEN (V3_AUTH_FIXED_PART_LEN + 8 + 16)
+/** Structure to hold all the certificates we've received on an OR connection
+ */
typedef struct or_handshake_certs_t {
- /** DOCDOC */
+ /** True iff we originated this connection. */
int started_here;
- /** The cert for the key that's supposed to sign the AUTHENTICATE cell */
+ /** The cert for the 'auth' RSA key that's supposed to sign the AUTHENTICATE
+ * cell. Signed with the RSA identity key. */
tor_x509_cert_t *auth_cert;
- /** DOCDOC */
+ /** The cert for the 'link' RSA key that was used to negotiate the TLS
+ * connection. Signed with the RSA identity key. */
tor_x509_cert_t *link_cert;
- /** A self-signed identity certificate */
+ /** A self-signed identity certificate: the RSA identity key signed
+ * with itself. */
tor_x509_cert_t *id_cert;
- /** DOCDOC */
- struct tor_cert_st *ed_id_sign_cert;
+ /** The Ed25519 signing key, signed with the Ed25519 identity key. */
+ struct tor_cert_st *ed_id_sign;
+ /** A digest of the X509 link certificate for the TLS connection, signed
+ * with the Ed25519 siging key. */
+ struct tor_cert_st *ed_sign_link;
+ /** The Ed25519 authentication key (that's supposed to sign an AUTHENTICATE
+ * cell) , signed with the Ed25519 siging key. */
+ struct tor_cert_st *ed_sign_auth;
+ /** The Ed25519 identity key, crosssigned with the RSA identity key. */
+ uint8_t *ed_rsa_crosscert;
+ /** The length of <b>ed_rsa_crosscert</b> in bytes */
+ size_t ed_rsa_crosscert_len;
} or_handshake_certs_t;
/** Stores flags and information related to the portion of a v2/v3 Tor OR
diff --git a/src/or/torcert.c b/src/or/torcert.c
index ef7775e..cff1ed1 100644
--- a/src/or/torcert.c
+++ b/src/or/torcert.c
@@ -420,7 +420,7 @@ or_handshake_certs_new(void)
return tor_malloc_zero(sizeof(or_handshake_certs_t));
}
-/** DODCDOC */
+/** Release all storage held in <b>certs</b> */
void
or_handshake_certs_free(or_handshake_certs_t *certs)
{
@@ -428,8 +428,14 @@ or_handshake_certs_free(or_handshake_certs_t *certs)
return;
tor_x509_cert_free(certs->auth_cert);
+ tor_x509_cert_free(certs->link_cert);
tor_x509_cert_free(certs->id_cert);
+ tor_cert_free(certs->ed_id_sign);
+ tor_cert_free(certs->ed_sign_link);
+ tor_cert_free(certs->ed_sign_auth);
+ tor_free(certs->ed_rsa_crosscert);
+
memwipe(certs, 0xBD, sizeof(*certs));
tor_free(certs);
}
@@ -477,9 +483,145 @@ or_handshake_certs_rsa_ok(int severity,
return 1;
}
+/** Check all the ed25519 certificates in <b>certs</b> against each other, and
+ * against the peer certificate in <b>tls</b> if appropriate. On success,
+ * return 0; on failure, return a negative value and warn at level
+ * <b>severity</b> */
int
-or_handshake_certs_ed25519_ok(or_handshake_certs_t *certs)
+or_handshake_certs_ed25519_ok(int severity,
+ or_handshake_certs_t *certs,
+ tor_tls_t *tls,
+ time_t now)
{
- (void) certs;
- return 0;
+ ed25519_checkable_t check[10];
+ unsigned n_checkable = 0;
+ time_t expiration = TIME_MAX;
+
+#define ADDCERT(cert, pk) \
+ do { \
+ tor_assert(n_checkable < ARRAY_LENGTH(check)); \
+ if (tor_cert_get_checkable_sig(&check[n_checkable++], cert, pk, \
+ &expiration) < 0) \
+ ERR("Could not get checkable cert."); \
+ } while (0)
+
+ if (! certs->ed_id_sign || !certs->ed_id_sign->signing_key_included)
+ ERR("No signing key");
+ ADDCERT(certs->ed_id_sign, NULL);
+
+ if (certs->started_here) {
+ if (! certs->ed_sign_link)
+ ERR("No link key");
+ {
+ /* check for a match with the TLS cert. */
+ tor_x509_cert_t *peer_cert = tor_tls_get_peer_cert(tls);
+ /* XXXX Does 'cert' match spec in this case? I hope so; if not, fix
+ * spec */
+ if (!peer_cert)
+ ERR("No x509 peer cert");
+ const common_digests_t *peer_cert_digests =
+ tor_x509_cert_get_cert_digests(peer_cert);
+ int okay = tor_memeq(peer_cert_digests->d[DIGEST_SHA256],
+ certs->ed_sign_link->signed_key.pubkey,
+ DIGEST256_LEN);
+ tor_x509_cert_free(peer_cert);
+ if (!okay)
+ ERR("link certificate does not match TLS certificate");
+ }
+
+ ADDCERT(certs->ed_sign_link, &certs->ed_id_sign->signed_key);
+
+ } else {
+ if (! certs->ed_sign_auth)
+ ERR("No link authentiction key");
+ ADDCERT(certs->ed_sign_auth, &certs->ed_id_sign->signed_key);
+ }
+
+ if (expiration < now) {
+ ERR("At least one certificate expired.");
+ }
+
+ /* Okay, we've gotten ready to check all the Ed25519 certificates.
+ * Now, we are going to check the RSA certificate's cross-certification
+ * with the ED certificates.
+ *
+ * FFFF In the future, we might want to make this optional.
+ */
+
+ tor_x509_cert_t *rsa_id_cert = certs->id_cert;
+ if (!rsa_id_cert) {
+ ERR("Missing legacy RSA ID certificate");
+ }
+ if (! tor_tls_cert_is_valid(severity, rsa_id_cert, rsa_id_cert, now, 1)) {
+ ERR("The legacy RSA ID certificate was not valid");
+ }
+ crypto_pk_t *rsa_id_key = tor_tls_cert_get_key(rsa_id_cert);
+
+ if (rsa_ed25519_crosscert_check(certs->ed_rsa_crosscert,
+ certs->ed_rsa_crosscert_len,
+ rsa_id_key,
+ &certs->ed_id_sign->signing_key,
+ now) < 0) {
+ crypto_pk_free(rsa_id_key);
+ ERR("Invalid/missing RSA crosscert");
+ }
+ crypto_pk_free(rsa_id_key);
+ rsa_id_key = NULL;
+
+ /* FFFF We could save a little time in the client case by queueing
+ * this batch to check it later, along with the signature from the
+ * AUTHENTICATE cell. That will change our data flow a bit, though,
+ * so I say "postpone". */
+
+ if (ed25519_checksig_batch(NULL, check, n_checkable) < 0) {
+ ERR("At least one Ed25519 certificate was badly signed");
+ }
+
+ return 1;
+}
+
+
+/**
+ * Check the Ed certificates and/or the RSA certificates, as appropriate. If
+ * we obtained an Ed25519 identity, set *ed_id_out. If we obtained an RSA
+ * identity, set *rs_id_out. Otherwise, set them both to NULL.
+ */
+void
+or_handshake_certs_check_both(int severity,
+ or_handshake_certs_t *certs,
+ tor_tls_t *tls,
+ time_t now,
+ const ed25519_public_key_t **ed_id_out,
+ const common_digests_t **rsa_id_out)
+{
+ tor_assert(ed_id_out);
+ tor_assert(rsa_id_out);
+
+ *ed_id_out = NULL;
+ *rsa_id_out = NULL;
+
+ if (certs->ed_id_sign) {
+ if (or_handshake_certs_ed25519_ok(severity, certs, tls, now)) {
+ tor_assert(certs->ed_id_sign);
+ tor_assert(certs->id_cert);
+
+ *ed_id_out = &certs->ed_id_sign->signing_key;
+ *rsa_id_out = tor_x509_cert_get_id_digests(certs->id_cert);
+
+ /* If we reached this point, we did not look at any of the
+ * subsidiary RSA certificates, so we'd better just remove them.
+ */
+ tor_x509_cert_free(certs->link_cert);
+ tor_x509_cert_free(certs->auth_cert);
+ certs->link_cert = certs->auth_cert = NULL;
+ }
+ /* We do _not_ fall through here. If you provided us Ed25519
+ * certificates, we expect to verify them! */
+ } else {
+ /* No ed25519 keys given in the CERTS cell */
+ if (or_handshake_certs_rsa_ok(severity, certs, tls, now)) {
+ *rsa_id_out = tor_x509_cert_get_id_digests(certs->id_cert);
+ }
+ }
+
}
diff --git a/src/or/torcert.h b/src/or/torcert.h
index 143a2aa..f7ca0ff 100644
--- a/src/or/torcert.h
+++ b/src/or/torcert.h
@@ -84,6 +84,16 @@ int or_handshake_certs_rsa_ok(int severity,
or_handshake_certs_t *certs,
tor_tls_t *tls,
time_t now);
+int or_handshake_certs_ed25519_ok(int severity,
+ or_handshake_certs_t *certs,
+ tor_tls_t *tls,
+ time_t now);
+void or_handshake_certs_check_both(int severity,
+ or_handshake_certs_t *certs,
+ tor_tls_t *tls,
+ time_t now,
+ const ed25519_public_key_t **ed_id_out,
+ const common_digests_t **rsa_id_out);
#endif
1
0

[tor/master] Label a few conditions in link authentication code as bugs.
by nickm@torproject.org 03 Nov '16
by nickm@torproject.org 03 Nov '16
03 Nov '16
commit a90a111a5f1c2f0c18c9e2baaa6eccd8c7111723
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Sep 9 15:50:33 2016 -0400
Label a few conditions in link authentication code as bugs.
---
src/or/connection_or.c | 31 ++++++++++++++++++++++++-------
1 file changed, 24 insertions(+), 7 deletions(-)
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 37af617..112a2c8 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -2329,8 +2329,12 @@ connection_or_send_auth_challenge_cell(or_connection_t *conn)
cell = var_cell_new(auth_challenge_cell_encoded_len(ac));
ssize_t len = auth_challenge_cell_encode(cell->payload, cell->payload_len,
ac);
- if (len != cell->payload_len)
+ if (len != cell->payload_len) {
+ /* LCOV_EXCL_START */
+ log_warn(LD_BUG, "Encoded auth challenge cell length not as expected");
goto done;
+ /* LCOV_EXCL_STOP */
+ }
cell->command = CELL_AUTH_CHALLENGE;
connection_or_write_var_cell_to_buf(cell, conn);
@@ -2514,23 +2518,30 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
set_uint16(result->payload, htons(authtype));
if ((len = auth1_encode(out, outlen, auth, ctx)) < 0) {
- log_warn(LD_OR, "Unable to encode signed part of AUTH1 data.");
+ /* LCOV_EXCL_START */
+ log_warn(LD_BUG, "Unable to encode signed part of AUTH1 data.");
goto err;
+ /* LCOV_EXCL_STOP */
}
if (server) {
auth1_t *tmp = NULL;
ssize_t len2 = auth1_parse(&tmp, out, len, ctx);
if (!tmp) {
- log_warn(LD_OR, "Unable to parse signed part of AUTH1 data.");
+ /* LCOV_EXCL_START */
+ log_warn(LD_BUG, "Unable to parse signed part of AUTH1 data that we just "
+ "encoded");
goto err;
+ /* LCOV_EXCL_STOP */
}
result->payload_len = (tmp->end_of_signed - result->payload);
-
+
auth1_free(tmp);
if (len2 != len) {
- log_warn(LD_OR, "Mismatched length when re-parsing AUTH1 data.");
+ /* LCOV_EXCL_START */
+ log_warn(LD_BUG, "Mismatched length when re-parsing AUTH1 data.");
goto err;
+ /* LCOV_EXCL_STOP */
}
goto done;
}
@@ -2538,8 +2549,10 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
if (ed_signing_key && is_ed) {
ed25519_signature_t sig;
if (ed25519_sign(&sig, out, len, ed_signing_key) < 0) {
- log_warn(LD_OR, "Unable to sign ed25519 cert");
+ /* LCOV_EXCL_START */
+ log_warn(LD_BUG, "Unable to sign ed25519 authentication data");
goto err;
+ /* LCOV_EXCL_STOP */
}
auth1_setlen_sig(auth, ED25519_SIG_LEN);
memcpy(auth1_getarray_sig(auth), sig.sig, ED25519_SIG_LEN);
@@ -2563,8 +2576,10 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn,
len = auth1_encode(out, outlen, auth, ctx);
if (len < 0) {
- log_warn(LD_OR, "Unable to encode signed AUTH1 data.");
+ /* LCOV_EXCL_START */
+ log_warn(LD_BUG, "Unable to encode signed AUTH1 data.");
goto err;
+ /* LCOV_EXCL_STOP */
}
tor_assert(len + AUTH_CELL_HEADER_LEN <= result->payload_len);
result->payload_len = len + AUTH_CELL_HEADER_LEN;
@@ -2606,8 +2621,10 @@ connection_or_send_authenticate_cell,(or_connection_t *conn, int authtype))
get_current_auth_keypair(),
0 /* not server */);
if (! cell) {
+ /* LCOV_EXCL_START */
log_warn(LD_BUG, "Unable to compute authenticate cell!");
return -1;
+ /* LCOV_EXCL_STOP */
}
connection_or_write_var_cell_to_buf(cell, conn);
var_cell_free(cell);
1
0
commit f156156d56ec61394eb814397c33557762870809
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu Sep 22 11:22:11 2016 -0400
Audit use of tor_tls_cert_get_key().
This function is allowed to return NULL if the certified key isn't
RSA. But in a couple of places we were treating this as a bug or
internal error, and in one other place we weren't checking for it at
all!
Caught by Isis during code review for #15055. The serious bug was
only on the 15055 branch, thank goodness.
---
src/common/tortls.c | 2 +-
src/or/channeltls.c | 10 +++-------
src/or/torcert.c | 3 +++
3 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/common/tortls.c b/src/common/tortls.c
index eb24411..e3550b2 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -814,7 +814,7 @@ tor_tls_get_my_client_auth_key(void)
/**
* Return a newly allocated copy of the public key that a certificate
- * certifies. Return NULL if the cert's key is not RSA.
+ * certifies. Watch out! This returns NULL if the cert's key is not RSA.
*/
crypto_pk_t *
tor_tls_cert_get_key(tor_x509_cert_t *cert)
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index f5b81f0..a3e1f8c 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -1955,9 +1955,7 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan)
identity_rcvd = tor_tls_cert_get_key(id_cert);
if (!identity_rcvd) {
- //LCOV_EXCL_START
- ERR("Internal error: Couldn't get RSA key from ID cert.");
- //LCOV_EXCL_STOP
+ ERR("Couldn't get RSA key from ID cert.");
}
memcpy(chan->conn->handshake_state->authenticated_rsa_peer_id,
id_digests->d[DIGEST_SHA1], DIGEST_LEN);
@@ -2242,10 +2240,8 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan)
size_t keysize;
int signed_len;
- if (BUG(!pk)) {
- // LCOV_EXCL_START
- ERR("Internal error: couldn't get RSA key from AUTH cert.");
- // LCOV_EXCL_STOP
+ if (! pk) {
+ ERR("Couldn't get RSA key from AUTH cert.");
}
crypto_digest256(d, (char*)auth, V3_AUTH_BODY_LEN, DIGEST_SHA256);
diff --git a/src/or/torcert.c b/src/or/torcert.c
index d100298..69f50aa 100644
--- a/src/or/torcert.c
+++ b/src/or/torcert.c
@@ -559,6 +559,9 @@ or_handshake_certs_ed25519_ok(int severity,
ERR("Missing RSA->Ed25519 crosscert");
}
crypto_pk_t *rsa_id_key = tor_tls_cert_get_key(rsa_id_cert);
+ if (!rsa_id_key) {
+ ERR("RSA ID cert had no RSA key");
+ }
if (rsa_ed25519_crosscert_check(certs->ed_rsa_crosscert,
certs->ed_rsa_crosscert_len,
1
0

[tor/master] Document two additional functions in src/or/routerkeys.c.
by nickm@torproject.org 03 Nov '16
by nickm@torproject.org 03 Nov '16
03 Nov '16
commit a53059c6a0398bf2a74e08c3902e8a994e5fa120
Author: Isis Lovecruft <isis(a)torproject.org>
Date: Wed Sep 21 19:34:18 2016 +0000
Document two additional functions in src/or/routerkeys.c.
Adds docstrings for generate_ed_link_cert() and should_make_new_ed_keys().
---
src/or/routerkeys.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/src/or/routerkeys.c b/src/or/routerkeys.c
index f0f6252..0aeb2f9 100644
--- a/src/or/routerkeys.c
+++ b/src/or/routerkeys.c
@@ -927,7 +927,18 @@ load_ed_keys(const or_options_t *options, time_t now)
return -1;
}
-/* DOCDOC */
+/**
+ * Retrieve our currently-in-use Ed25519 link certificate and id certificate,
+ * and, if they would expire soon (based on the time <b>now</b>, generate new
+ * certificates (without embedding the public part of the signing key inside).
+ *
+ * The signed_key from the expiring certificate will be used to sign the new
+ * key within newly generated X509 certificate.
+ *
+ * Returns -1 upon error. Otherwise, returns 0 upon success (either when the
+ * current certificate is still valid, or when a new certificate was
+ * successfully generated).
+ */
int
generate_ed_link_cert(const or_options_t *options, time_t now)
{
@@ -967,6 +978,17 @@ generate_ed_link_cert(const or_options_t *options, time_t now)
#undef SET_KEY
#undef SET_CERT
+/**
+ * Return 1 if any of the following are true:
+ *
+ * - if one of our Ed25519 signing, auth, or link certificates would expire
+ * soon w.r.t. the time <b>now</b>,
+ * - if we do not currently have a link certificate, or
+ * - if our cached Ed25519 link certificate is not same as the one we're
+ * currently using.
+ *
+ * Otherwise, returns 0.
+ */
int
should_make_new_ed_keys(const or_options_t *options, const time_t now)
{
1
0

[tor/master] Move unittests' RSA pregen code into a new file, and improve.
by nickm@torproject.org 03 Nov '16
by nickm@torproject.org 03 Nov '16
03 Nov '16
commit acbb60cd6310d30c8cb7631ee52ce86150021ab1
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Sun Sep 11 12:36:09 2016 -0400
Move unittests' RSA pregen code into a new file, and improve.
This patch moves the pregenerated RSA key logic into a new
testing_rsakeys.c.
Also, it adds support for RSA2048, since the link handshake tests
want that.
Also, it includes pregenerated keys, rather than trying to actually
generate the keys at startup, since generating even a small handful
of RSA2048 keys makes for an annoying delay.
---
src/test/include.am | 2 +
src/test/test.h | 2 +
src/test/testing_common.c | 69 +-----
src/test/testing_rsakeys.c | 545 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 550 insertions(+), 68 deletions(-)
diff --git a/src/test/include.am b/src/test/include.am
index 0aff395..17491df 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -128,6 +128,7 @@ src_test_test_SOURCES = \
src/test/test_helpers.c \
src/test/test_dns.c \
src/test/testing_common.c \
+ src/test/testing_rsakeys.c \
src/ext/tinytest.c
src_test_test_slow_SOURCES = \
@@ -135,6 +136,7 @@ src_test_test_slow_SOURCES = \
src/test/test_crypto_slow.c \
src/test/test_util_slow.c \
src/test/testing_common.c \
+ src/test/testing_rsakeys.c \
src/ext/tinytest.c
src_test_test_memwipe_SOURCES = \
diff --git a/src/test/test.h b/src/test/test.h
index bf1f53d..bbbc87c 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -74,6 +74,8 @@
const char *get_fname(const char *name);
struct crypto_pk_t *pk_generate(int idx);
+void init_pregenerated_keys(void);
+void free_pregenerated_keys(void);
#define US2_CONCAT_2__(a, b) a ## __ ## b
#define US_CONCAT_2__(a, b) a ## _ ## b
diff --git a/src/test/testing_common.c b/src/test/testing_common.c
index fd7c4e7..deb11d0 100644
--- a/src/test/testing_common.c
+++ b/src/test/testing_common.c
@@ -155,65 +155,6 @@ remove_directory(void)
rm_rf(temp_dir);
}
-/** Define this if unit tests spend too much time generating public keys*/
-#define CACHE_GENERATED_KEYS
-
-#define N_PREGEN_KEYS 11
-static crypto_pk_t *pregen_keys[N_PREGEN_KEYS];
-static int next_key_idx;
-
-/** Generate and return a new keypair for use in unit tests. If we're using
- * the key cache optimization, we might reuse keys. "idx" is ignored.
- * Our only guarantee is that we won't reuse a key till this function has been
- * called several times. The order in which keys are returned is slightly
- * randomized, so that tests that depend on a particular order will not be
- * reliable. */
-crypto_pk_t *
-pk_generate(int idx)
-{
- (void) idx;
-#ifdef CACHE_GENERATED_KEYS
- /* Either skip 1 or 2 keys. */
- next_key_idx += crypto_rand_int_range(1,3);
- next_key_idx %= N_PREGEN_KEYS;
- return crypto_pk_dup_key(pregen_keys[next_key_idx]);
-#else
- crypto_pk_t *result;
- int res;
- result = crypto_pk_new();
- res = crypto_pk_generate_key__real(result);
- tor_assert(!res);
- return result;
-#endif
-}
-
-#ifdef CACHE_GENERATED_KEYS
-static int
-crypto_pk_generate_key_with_bits__get_cached(crypto_pk_t *env, int bits)
-{
- if (bits != 1024)
- return crypto_pk_generate_key_with_bits__real(env, bits);
-
- crypto_pk_t *newkey = pk_generate(0);
- crypto_pk_assign_(env, newkey);
- crypto_pk_free(newkey);
- return 0;
-}
-#endif
-
-/** Free all storage used for the cached key optimization. */
-static void
-free_pregenerated_keys(void)
-{
- unsigned idx;
- for (idx = 0; idx < N_PREGEN_KEYS; ++idx) {
- if (pregen_keys[idx]) {
- crypto_pk_free(pregen_keys[idx]);
- pregen_keys[idx] = NULL;
- }
- }
-}
-
static void *
passthrough_test_setup(const struct testcase_t *testcase)
{
@@ -339,15 +280,7 @@ main(int c, const char **v)
}
tor_set_failed_assertion_callback(an_assertion_failed);
-#ifdef CACHE_GENERATED_KEYS
- for (i = 0; i < N_PREGEN_KEYS; ++i) {
- pregen_keys[i] = crypto_pk_new();
- int r = crypto_pk_generate_key(pregen_keys[i]);
- tor_assert(r == 0);
- }
- MOCK(crypto_pk_generate_key_with_bits,
- crypto_pk_generate_key_with_bits__get_cached);
-#endif
+ init_pregenerated_keys();
atexit(remove_directory);
diff --git a/src/test/testing_rsakeys.c b/src/test/testing_rsakeys.c
new file mode 100644
index 0000000..66684fc
--- /dev/null
+++ b/src/test/testing_rsakeys.c
@@ -0,0 +1,545 @@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2016, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "or.h"
+#include "test.h"
+
+/** Define this if unit tests spend too much time generating public keys.
+ * This module is meant to save time by using a bunch of pregenerated RSA
+keys among */
+#define USE_PREGENERATED_RSA_KEYS
+
+#ifdef USE_PREGENERATED_RSA_KEYS
+
+static const char *PREGEN_KEYS_1024[] = {
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICWwIBAAKBgQCZa39BCgq7KWBWFSjGYHhqmTCHvQ7WNEFAb9Mujb6Xn/Zy01fu\n"
+"WIpVvqmAKeLNEziItUm/gB8GwAN+/ZLwL9pufjIp2Ar+yqVXKySioZQxuCgTP2wm\n"
+"Ku0OfmAra1Xbtrkc2OCJllxkyNPrJ/kxfwjWR96UP0+VMbOlkBoEH1FtvwIDAQAB\n"
+"AoGAUXoygeMIYe+OdwkTt48CRHKIwH3aRE5KHSOGPyIOB05vvvmYqD8jcHgqYqNc\n"
+"DNdZXdkRin9LevU8phObFq4DTXp08XggUx4Kk4AdsFKubQtJ8gHm3xlSKbZXX2m/\n"
+"ZF0GRaZtVDQ3TRGh+OBLILt/2jT+BaFKGAyJ7al76F2nprECQQDJyLlteLDFBmrd\n"
+"0kAjNBE50S5YskBCQeQACROfyTKW8lG1J57UBeYjXvbrDFBR4alIS9DEexGai9Gz\n"
+"wxpgKg2nAkEAwqQmPstjHxvqGQRi41uXO026MLxY7dhEqs1aSw3tuT8v17pW3OEa\n"
+"Qxv7JINePZ3+sNN+Ic+3RXBR0QuD7lSSKQJAZjVSF21GvMXfY7SX4D0DbLHUNAE2\n"
+"I1mUz5/JXOpgwazETmpfPS4vwELd93kpRhBz2rbsbFmaNRoVgmSU+5jRiQJAZ1bV\n"
+"g2NilgKxEGU2x3U6Xt8Oqo9lO6omEvUCKnUTsNWuZf/l3FGbKuQxO5qPr3Ex5tny\n"
+"zqrEqBZRKgbOHfxCuQJAbJY5C3Nm5koemr031r00MY2YD1b6+hyKZyPdZ21HpyY8\n"
+"z1kWShL0POjYPX/BnKE1FkpklWcKBb7wkK7dvAKkEQ==\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXQIBAAKBgQCyqMM2TfFGV5tVBTVabxLVln8146nDavIdR6q78DCUMh8Zfzkk\n"
+"h9Lbl1NX4RU+AmrCZMPq21/EjIRxRQyRdgPYJVLdp96eGeYnEzmMkqvXiswXvDg/\n"
+"tXqsjyJeYsoHMQWDTpCLfjYo4K1ol1sg8VIs4wQeq5og6QSdmhBoz7MyqQIDAQAB\n"
+"AoGBAIJekey7nZeV8Bxva4ptSRIg+v0I/2VBUiG5nUX9NIW/uV/yrXERx/VDjKaw\n"
+"8b5JJzxpKWnk4RJc83xwRYaT1qMYHiQfybxEI0K9SjhtaThAjtXkQGtZgLJILl3t\n"
+"yh3LPTh1ocwafsKjU6eGYAe/DYn9/QwYHbtyaimcigu4etp9AkEA2DgC+HndoP1i\n"
+"np26Lx+4TG0vAfrVYGSLT9FXwf2iBV3oJvdKqu6wr8ipb1SbshRPcOQd31/mCh6+\n"
+"2BR+d4ddcwJBANOHrlBbGZdHnoEu6kKbPwwkc31IZYqyfSpkqm0Lb2oWZ9SInKfc\n"
+"cz0qpH91p610XUpYmycaJr4K+N8jgrz86HMCQQCoqGBg1Ca2OpCf66bctWB8dTqS\n"
+"z8d7rlIhC8npr1+f0hWRt5pN5Wx7YgoQpq3gZgllpPtMT7DQOhVh1fKkaDnTAkA4\n"
+"XuskPPLX7t0dvhvtviOSH9CrLXTp/mD+wC7uumJpmij3aaSd01DelxOZaAhUYDNQ\n"
+"UcafKAf1E0V5aaQ4qwljAkA9NVN6CtpzzcLrstTKxrx5P1Ylt/0UYQDo1lIaqwrT\n"
+"aOFbXmOungiC9+p/4U7RbX0MEzjFDHCWlaHASviGVgta\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICWwIBAAKBgQDDt2V63APj3JSqaRgofUzhtB+prm0wII4uHyxfOxnpYIELOW5z\n"
+"3UHmkr+B4D+Nif5jIp0i6W4OS4S+YHewKsDsXvXKRIW78KzOt6Le4JI9rSarNjy5\n"
+"aJKksWQRALLCmxP/BdolaBFqF3fIPD5+Zxu8ESgxhkEQI4p7awUp3E730QIDAQAB\n"
+"AoGAZktfAR4p8lkCYydW9yK2ommQ+xEuBK+fYL/uYz/yxSYpjIJSFsEYhrlA21Mo\n"
+"JIRxr8MRuoOjgFk8YnztUeimuHpslDlZDaCBzjRjBRFCMepZNG9xqSEL0u7C+SH6\n"
+"KU5f2x2P6PneBj6WaHZM+6Lf2xHlOoeuaVSUfq2Pk2VBF9kCQQDtawWWNwP0+xea\n"
+"oCAQpanaLzYPjlqZfHJQ1AAI5eSkdf1qmlypIHwOtjAEa6XuEO/Or8RNkNy4nQdw\n"
+"qhcQ7PXDAkEA0wjT6Z+Lrt67FnwPgoSvl4Nukcqw4OWHbBKhaQPsO9+oc3PAXLdD\n"
+"SclUUqDF6NX1yONTV1KrPdz4zElmEua+2wJABm4inZnp2oW+cuqpU6oY+pbSwQMb\n"
+"AxMyyWukgJkxYx7q+SsrHU2K7p8Sl9wOh28f/5oVGAC3aayfGfcRXtz8HwJAIqeO\n"
+"dQzYGU1GF7kjquEzHIRewd4xEZ1fkaW1j9MvFd3ygZL+gbsud41yJWd1WHjaNbTu\n"
+"2KYgrLX+vT1IX844hQJAbg0V7iHlttQqXL7yN09jIjQLprqVhDZCUHS9s9Dxe7fz\n"
+"Ac0ZZD0D6EVNmSmBB71q7kLUWX/W/10d447TLnnfew==\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXgIBAAKBgQDhCAjPEockl4lqkvoIb5O3NJJG8NWD31c63e/cPWY6MX5nOM/q\n"
+"avof2eWJxFOk0HQ2BRVwIgNex6kLxtsdw7XE0A5uZorTp9DbRCGMqUqHNhHH9ci2\n"
+"mMPP9jptq3ieWg310bH4Tad8h3WE2npSCDBvxyV6EmuH2rlQW9ZlHNoiRQIDAQAB\n"
+"AoGBAI4PgWggPTqng7PJF5mNvsYQpSutzE0VCL977nmuNUQVjMPjRLarVD4ZU+QW\n"
+"EevhQQv9R5xjjJcgGqL5pchzjeKDm0/LA+AygnZoDMs2O68Neieqvr7cPqr5ALGs\n"
+"WuZvSn+bRJTenvV9sUh2ii0/u3GQbL1v7GWDkIdD7itDbmRhAkEA8iijuEY+W67w\n"
+"7JusjY2MQ2Cm6xxxR0YcnYPzT6UDm+Z7NNJwKscQ6AjayNmxmXGpbUdukzLzXf8y\n"
+"fccI9t6iHQJBAO3kx9nZay0Ktl51QP5o2gwoqRIbnogGfR06KJOlzIPGR0aPn8cg\n"
+"uKq2SiyjewEaSBM6S/4UlxYUmvc3VKnxCEkCQQDpTjg2YQ7RPGIIRA/iLV7Wx3bq\n"
+"C/QjjCwjoi44LK6mdE9928WPoUzrkSRg4EQYpwZqL6kcDrmkdSuLPMipOGQNAkA3\n"
+"KtzlujPOiDNuiEaAORSHyU4b8ue6p7aP9pK+Wq6oyGxzAo+NABuTCx78ZxT5Vnzs\n"
+"aJKC44d+CV0+g0hQ+KJxAkEAqFYzNWIzTHX8DVDdK9BpUaBg1DFxIeP5Kk+/X3FF\n"
+"5BafG08B6OiLf8qIGGsxLXNRjIE0GVp3Sy23FUKtUymP+A==\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXQIBAAKBgQDMDk01VwPxQq/BAwOBmfGUP/x5BQn+uxI0Aat6bdWuz/2CsjbS\n"
+"CWD/YLCaPm+DpHp9RMwk4HONJaw4B2XOw3ELPx7y9DEgdC1wZ9wRkJmqr2IJZoZR\n"
+"C7x43nNv+/IXTiRkkljCcMpoL1Tld+L2VbmWR29PdZwvspWRILkEZu1mNwIDAQAB\n"
+"AoGANvFK3KfXSei4xfF3yjeXEmHAKx2uOUZJenNQpqBYPr+F9ODjXd5knZ59LqrM\n"
+"/9cTnBMgHHXK5yBTpKppQSjikLeQ2BF04Ktff9oGqVcS9x/rKo0CREuxsEfawZOW\n"
+"OzOWENp4YcDKGP1I/Ctr185QzStaWrXVQftxmYQ53T77ShECQQDnhabwtqW7rfe4\n"
+"+MfkWEJ9Y2s6iMs3JWnwPOX9G9R39PiAD4vAghHJyHHttS9Ipxmvp0hThu0x7a4g\n"
+"8BfUpqgjAkEA4aFAmzarWKigREAACVTYH2RHpXbuk05vF9WqfMPiEvQUd5a1q6vc\n"
+"xkGZsE3v/TExLjPRZP4FeUNV5sD7THzA3QJBAJxPoRlNx3GCEAlDdfnWGPX9JI09\n"
+"hC40RWUcSI7ttjJTI1+an1kWuBnLChhaRpU/tFjikTNLmmMmPHUihIRfDI8CQG7g\n"
+"3WzpKr8A7vFbOilbxnF2yDaqAYfmTXW7DHMPl/OUetJh/5kDdhT/e9VGF5+nIvH/\n"
+"iPFGW85Bpt8lCtmFnQkCQQDjpp9iy2qesE7KKX4Kv3++QfCJ2w3g7lwg4iyncoDd\n"
+"JrM53p29HROM21R6eekvqeWIe9tEX754b+E/N60ZjpGm\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXgIBAAKBgQDdDn3H+Eu0AW5GKohqDBntw6ubnd3VaJwZGzZyga4J2kLg8peP\n"
+"RAW6GDD6pcHzW+KZbFWHtRk70FSwvmyGcf+DY0r5tfyCHyDGmbJyPR0o6OVCgSFl\n"
+"ccf4eDvbyszzMdlx3uL05ABIpCShoKtEUqvyIQla3Jon+QBwuVkizMzyVwIDAQAB\n"
+"AoGACoKh4Fwh3VEkGRn0mnYw1Wk0Q5Xh8j+jDF6K3C7mQ3mpLGDca+dkDlEQIxq2\n"
+"egeoYnsQJf+qT3m8TRsAtfO9nj7+7IX4BfCtdIi4RNcorbs5YMWtFyaywnM6SQjS\n"
+"+1qf74aL4On9WRO2FtvnTMjFAAkiWNbQp7mWwTmB59i620ECQQDwde6/PwhUzvZh\n"
+"dyslKJdna5RjkDQyDIuh0zD/tFZ0Iko7Luec8q6n52ev/n0OiTLGetUh8goePsPP\n"
+"HVZHidNJAkEA61eMCmmu+GCAg2vJRtL5sDakAXsbP5M9Bf/QVHXtc4EVXHC6T2ld\n"
+"bldOJriNbBThBuPNmlQbssn9FApkyWT4nwJBAIuHIv3+CUuMvBJaH8L0BsaP+g67\n"
+"wk24Ud2Yujnl3rSMoR4uXV8IwqfS8quAs/gXTEs3QyzrUUuzh9NKZqIkK2ECQQCz\n"
+"vivBEDKIlPvSZBJYO25kfXcJgoKvLb9fw5/TwjXXD/HGpnpFiI3JZnjT7gRlVhT/\n"
+"9CDmC/MTvF3EXqPXhXy1AkEAo3a2me23Ljmub21jycSKaCk09dK85QTRRMe9c/hs\n"
+"i+pcGi9ZZW0Mm7cyQo47oXjNurkkv0fEvXIobVTEXAGU7w==\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXAIBAAKBgQCv8R1IbfYnE3R3kNeezJ7m02XnyCBDDy0YfrQldQ+urdg1CFye\n"
+"bO0iPniJb8fmV8NW7x6nUZTDznCg+igroKXtK/w0WYmJJiH4A7Oi5xNjAfRIPvJ/\n"
+"J5GI8szS8rH8tp8pW1h8k/kNg2pnBjwQ2U9omhp95RGaHDQSRYzzH/fEFQIDAQAB\n"
+"AoGAcy7+BcH/iZuB/xjzIIJDcUhqibCJ9n0D/+pLU85sYuZrCmUcBZe4M1gEn61v\n"
+"iExilRJc1hthskL/l1POYql8lk+aqeeDuh38fWJj60TCV/sENiuXOsTmoFVA5pNn\n"
+"lwlG8JlpBMsgr1fGqg1C/WLFfMmvXdKVGvpRqI06j7AYUa0CQQDfZ5rI+FhXBlxo\n"
+"PR5CM1LB90DuHUMW+Kqoj0c9d2esXEQM7UqQ/9BiBQbL6Py7Z3VwCxibOqyz7+V7\n"
+"2aGUMAKnAkEAyZy5Mu2tHs6YBBxPYam7huzMUYjddN7ixAZUyGwxQp9kTIF2NbSQ\n"
+"yVDjKrco3s2lO4qj4pSumwVe3GGlsi6G4wJAOOS3pIqqZK84BUvbUtyjLMZ9AKbv\n"
+"GQCG5ZpneB3ahyiQJAKiRL8BIJVLH87b3hYA8GHDCHUu2jwz4xCPd5+qbQJAV0TP\n"
+"pYvb9AnZI25drhiaY7z8dA6aTYxs/A0Bhf/PEteLwtIHKRgP1BR/QG4n8slxTGSm\n"
+"q91P9ypL9XkPECGzoQJBAIMvGEM7ZGevQHBjJ8HhU8IsgT4cYH/XEYb8jRy4F+Ui\n"
+"jKxHPxLuFK4urAZunNUNrqhT0PxbB7hRjtHZrmFkrcc=\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXQIBAAKBgQDSpmV8ncLwc8gXzdFsZGPDtMO7C/IN9jKCIK13WIseMg1APlMt\n"
+"PB5lMQ9fa3m9ZRU0L8HzRo+u/Xdos3yIBI38X2Avy0laGKnQxiOKaDT/5ZHeiBBh\n"
+"nMZjP2WY5V1sgqNP9RD8enE6WaSvq1j0BM++mn9KEe//5+dWD8tboBKF4QIDAQAB\n"
+"AoGBALgVoerdE1Z+WAY1XyaSNHz6o3H6ZnW9CTaex/jb7/dbVikmThnhx842qXCB\n"
+"w8m3ZGhOs/edWkNaTde5wsI6+LhVGco/PWxN4v61jokxUU+5KvUvGacXhXIjzKwG\n"
+"DrNCYmle62QCI1z4+TLQW/Lq+jw2Wzk70NWEvoP58gt5SJoBAkEA9wubRKRs49LW\n"
+"5JNQZ9hjc+mAfP9YK/sMe4jkdloMMWXjSMlF3Z4mI9XQSpfbBqwWIBXsjU/15LIS\n"
+"ftmujZsMKQJBANpJEZI7UFoRdSP7AlM0YJuXWnVGyn/K+VIeEso5AlZdKXCTpxqp\n"
+"9blWq0UVC6jLesZ5UNPuBiAnrBaVwDA8YvkCQF+FQVfdK607TJO80g4VAP9EfcXX\n"
+"BUScIUtytsN8NdKzzpnKGRWDnMOmXI87ABkoWLW3RGuvSyhOIhCiInfmR2ECQASc\n"
+"FmroJcJBLCAeZOYs7P1cLOTdIdmhB7LcP7lVit8YCJAADj9Z536KfgNvdleSNH2M\n"
+"glB3blmvfMrdTrm2DMECQQDj6GJ/Tc2rCsq534xknasVjrgtJMQFxmQCTVgBx9pc\n"
+"gTflJAHAmNDvstacVqeObLCF2ZIvya8fSXGbDOJYeGDv\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXAIBAAKBgQDGgUJAm7vf/3focNGwzv4TkzYF2XwpAirnb61dyxvfug1zKv2k\n"
+"AUg3qACiurR7JrI+kAbmxEnNaKV7ts7uO763wP9KE8YAuFZsp7NFA295rEZhw38T\n"
+"rUlWHMCeaZ3mqW2q8gA14C/ZJCG4gS91SIHLjNGsbHwr2Jvri2ItwIP8FQIDAQAB\n"
+"AoGAONceb32oiHWQkkBr6uL6ogRPPdGO2fdC7c5uqCLWsnOGEmpHAsVTNoym0fIA\n"
+"aBsmgv+e2klukKDccdZg3prA+z7lHcc2a4bIFguF6ei80hLIis/dds66fFXofCzy\n"
+"DMlkncSbJwIvQHG9gblxp9qSKElZF7XjABZEImarfUlakGkCQQD//msGy5N0ZhMI\n"
+"yGMXkwXRJXfmRrIrOqHx6u1eUp4OuqDW+hBz4KCHnWfuRJkNGQIammSf18jPasP5\n"
+"YHyr/LifAkEAxoJ8R8Vusexo9ZjuU44qXCSvJQ26UBV7mn6TGEAn2DRK1RWKDaHv\n"
+"j2vnRjt3CO9WPDQL7SB/1HNAy+dIMPyqywJBAIB6tESIz8zPniX+TJ18UKMTZwXP\n"
+"3YQMvVKpUdDRLjq+OBMtFizSRD9MJOlUzGvibUfkzTPcHRDcyNbUMj4vbIkCQBx4\n"
+"6sqAjvgGKKfRX52sbnb47AYsieSisC/gp8h6qzxfg7w8cqix6WJw36M7ND+b1Iqe\n"
+"DHfeiXc3cLvOWJRuKTECQCEYkujtSjXWb26xaESFWGtUI/nEvCyqYPQAFBpaGzQ3\n"
+"tiTDeKHzypesWYoTxOiNQWCQMLrFGuUbDpYOuDOVNjw=\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXQIBAAKBgQCcwSAfytnspSSDX/sKmCPOMnpuCYeWA4wbz1wLyb63a8/KXhhG\n"
+"6o2W0kt3x1vnGZkeWwZOeBFUqwoc+xHhoNcZFsMOyqbqA3UMZW5cx27MsexRTQHs\n"
+"Go1newu/E+8NNCohY51G7z1Hdo0L6mi/Tldh7puuGsMwKqNG/Vvo/GQDgwIDAQAB\n"
+"AoGBAIUdpBAbjXDe1OET0vYuOMnUKA/l29RS8tpy/zGrg1/0GCM8QNWIPfEEaL4w\n"
+"+CSKonMazYI5iE4kaZQuygKXOdFqKxX8nrGK2hR0DIEUHhhiqyGMUKrf4ELkAJzK\n"
+"tHtcO64OFEU2EGa72wCmyk2MhqhLxWxA7E00x24uvW6pen6xAkEAzHhbzlRgLZ+K\n"
+"QuXmQHEqkGaS2Ccf6c9TA5Bf5S2/5zBl+OqVyJJQH0yrbPYR6Nn1NeSv3R4IDJYg\n"
+"fSZLaVzWHQJBAMRCU6QtTnZoQ97pLvXCSKRYKJF+CnE3zDFTyoJrpK0W1FSnb1EE\n"
+"DWjjdSdMLynf/InX+VOaLk3Gxwjme4NKjh8CQQCg2b4/HplayrsVzY3I/D2jw02Z\n"
+"xY2RfYusrhMCU284DBbsLn8OfiuRs9rXqOyF5ZDFiNXgeROT8zYzvcBtbp7xAkBU\n"
+"ZET9IvJLXjhZISItUXbVHIeNUIqC9sBaMbKx9EGioF97a2gliT2O7cgRtuPM+ODq\n"
+"ETHILlNc5G3vuNRBt4x3AkBV98Y1SZA3TQlUVTsjGraxkFTfU1IlomiOdOwTQ+xZ\n"
+"x+JxhhgZwZ+kgI3PidEufFCTZJ3WO6Wk9gk18Bx7CLjm\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXgIBAAKBgQDq/K7wNW3fcTbaRTjNZlM4W0G7tKeO+X0bca4+9uin3ML3ogNJ\n"
+"6qT/B0QAZB6Vyi9kKa3E8plQkjmPuX8Q27zj2QjEuDZ12RGFnikeOosUhOYiDh3Z\n"
+"T9CHnr6stozzgk79Xd6VI7bqRcgRwbY0uc9QVr6vwddyIfSploSpVcgspQIDAQAB\n"
+"AoGBAJfUpo/sZc6uzxtfCKGmkPTj+ef3hSBbUZuu60AhtxfnC06HrwpOg0eJAUYj\n"
+"aqOsHMziJTYQ7kDiCjE0UMaqxDNS5hueumznq2xM2mSN0nYoktU00kpANVkW4VPA\n"
+"33TB16DyqlKq2/21Rs1g8/8+IKkKDbRLTC//1WqNHASQVoGNAkEA/+z4hxTVXZkr\n"
+"9hz29tAHKURlqzxUEKLnS0eL+XGJRNfGJ+65eXL+gFiIbTnpVeidL1+lKWkZyYzl\n"
+"75cNRdUHhwJBAOsOJ9mUOqTbLW5tzh18ewZGOa1JcxhOvf2E1d56N8tDK6lvoqkF\n"
+"oUUb8kIweDxPLCVLCl8qFrbjn619fxDInXMCQAfEZGKNIlCd5nSoumIRPDZnagKB\n"
+"aTe8CfMB7+CZLoZVWiE6IIzsDYdNqI5QFKHT1nlqmLOiCfNRAGV+GxwEdB8CQQDE\n"
+"sHu4HclU2fMSTOAE3H01qt3om2WsGXfyBI3SNQMrG3IVvkymkwd4BQKbUGPMU5Pl\n"
+"QP3U1CtdruuXCUSijrzxAkEAoqYub6+0zM8fakSQZcZ01TG9Fuo2xVFDCQsvqR3m\n"
+"ZhRT/oinIvOxSh4fQs40bmt1RBmc2L1Is6YB2NTVQEBZDQ==\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICWwIBAAKBgQCrf0rPvHYaGYQrc1ciRwaONs8TUvSVmUU98HMYXoFEkBL4CAGH\n"
+"4oNHFk8kXHEOsBED0eccSYegWhqKHSz7PbjmJaXloExWrtx5ea3Twf8VTgcfDWQP\n"
+"0TzD3G1TYjAFPQ1/LAZCpQFmwpMmTGGxegUhOzkpEWXdLVEVc9Uw4C4L2QIDAQAB\n"
+"AoGAZXAJZA5pHM7y6nBynYe9TOkGWru6h7H8zsImkcd0VoWRcrvpi+JjG+0KKsuy\n"
+"46kop0XEmWq0mhgxknfnX0QG1MKTqGMIUGN4qCaezOabIpCOdA4d/pr/mWoNgOWw\n"
+"9Kc/tNCrKxPKsQMAlWP6ktHN30XRSlHgAjSeUVUiNHztvTECQQDUNin2nyIvj8ZA\n"
+"QAsFW9qW+TiTkeUK6yiZ9Gvgf20gwZRWOe5/xnMxVvtN6v7Av1ew/l4VhBoj/w5g\n"
+"ydIZk+2LAkEAzuJwdt+ccllG19qmEcbo9XFafgi2PvlEjPJmT1rHV2ns/7HIMu27\n"
+"PJY36GgExSfFco6VmicaoOt+RKg+5acgqwJBAKQxAEjcGWQ5VsgRhTVxO3DChX7Q\n"
+"TColhrWPwwPhM/s7K92HVzwvvKL5TNmdr9xMb7n3Ja56FouxZVuH6/J0XT8CQAat\n"
+"Mhnz/3WFQg8HRGLAe5YoMVZt64u+uaKe1ARtlo9QoNBjqWVTXL6IzocWjEjcjrey\n"
+"uEtARdC5qNqIX3dD3H8CP3pVCPvpHOTxkUaktmLYowSA1HSfO9wkE6bMCHhkLwXF\n"
+"yTIJ+N7c5u5YN1B6hhVqpKbdnSv+K0MQ0xbfwOWNMw==\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXAIBAAKBgQDGQmrKfO3WovoXkOTSh/shO9qjbX4izhg4pccVU3Tp45v/dgAE\n"
+"uDUuaa/clToyH5AhOtuazO/asC3ZNajg1ia5VPzmQU3gtqiIZIEXFaOovPlOrXru\n"
+"wyQnxaGORndJwfDXicG6bUwI+PDpNq8c4VOTujReeF0r74qMSc7TQLVlUQIDAQAB\n"
+"AoGAakR/aTm9YibJVohbnl00xoOGlcLCsXU2lmaFZ3DsYdGWdD+TkvQJzW7ozJtQ\n"
+"Lj2sy6L4wujGR7nXWW3hr2IaLpoc1UoyJpieAZM5os6bMN+N4MCqdcZMlazMtSWV\n"
+"UDO7O7xQGFpcvvZmnfKCyluFaJ5K/tWxP+2TnS1/m0BDRIECQQD5DYvToA0eKBt+\n"
+"7K4eEI8pzDot9NlcL21D86kNgpmuY4pifALU7GvXr299JpFFiYa2A1JVRfpQaoI3\n"
+"hZzz0ze1AkEAy8opWJP+T2q4reD5Qq5UjjrHUXFID23KeJEjh5YF40/bHqyVpWVR\n"
+"UMntNgAzs+13vRij48Zn6I8GRhStaQ3ArQJASPyFS8GN1paeaDXoWPs1WWR2cF1f\n"
+"DbsAZHeVxVXOv+J//ZimI8wdVpodLCoPTLee+NxEVqUpVEPCYY8QjgwKOQJAATmj\n"
+"6f5pxvxzQ8hYd0gpBfngfOLbdgxI7VSiDAyg2G8AeDy9YZMsW/n6zRpPNUO2NpLR\n"
+"WWs18LX7aaxyJnGIuQJBAPPfy9pd4XEFsRBIIe3N23Gua1XkS/407RJtAGm73Vrt\n"
+"QhtWh3i6D5gfpEApMoaE8aaQQ7H0z+0Uh1t8SWesy10=\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICWwIBAAKBgQCc/M/X8etUqrxnmH3PyuAYLIPZhwNySch8qz9NB47izYjxzuBG\n"
+"GSls6H7WeKIrB8UJY1gW8TLkdOLcrI/0hTANNHEPaueOE0xdABFj7tAaiiGPIM25\n"
+"N0wc76me0ZAMYJrZTHk8JZK153y9wInYBwVZreXCVSVf11RuVwe+iFQa5QIDAQAB\n"
+"AoGAQC4XJtivdhDLL6snHFF7pkZkrQTGgu3pOhakrXA+mTigGQOTqvTUe8LdP/9X\n"
+"hTIK+tiTheWcAcxLhx5BSB0/VDKjYhS0ROpTc33Iq9KalOQaTJbBYGA4eagpQjwU\n"
+"jGwr9u2sUsM9WI/Jg0VvLSKhfnNwYIUzLpK3BbWb2qAdh+0CQQDQ2s/8DlibFSBK\n"
+"UsFK7lLpV8UgMk9CkaNM2BPzI8Hsjpp6s3pULVRd36m4YTSg15EEHv7bZ1N/+krX\n"
+"mXb9xUULAkEAwGy5wHsUSjTK+kntkNXjlCU/+9R+HFpzg9Bwm/PqXTBwEWeU24hV\n"
+"iRjPvqPtWFZrWi/nfcviuMaqtdliw1I1zwJAZ2mQxhtMYC2LuYFUWAe9YfClmJWQ\n"
+"jUOTef8bka5I3RqW/t5TWc7AEWMnpDXtWx6hnUrDolt9Cschu7MvKeQ9lQJAL18U\n"
+"46PpPNN+XNuyVoOxgRkihVasrUI/SeYYsuv7eHGiRUagyOLpW9T139LvbV3pE8zT\n"
+"So7VA/Q0towL2lX01QJAGcoBNNouSpum9+5NvGQK1XXsZweawE+pFR2BE5XcjG+n\n"
+"FnaLEUBX7nTxhTU2cSQET1PKRNp568a281NEna0nxw==\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXAIBAAKBgQDFOqqGG/VtIScxayZYZ+BT+hcs5W1bD5qRxunbG9O36UVT18UE\n"
+"CWw9HUf0Q5sDMGvVmBxwZ4GjbR5FDPfhIXaRCzobnejJXq/0k+O5NAVkcSPtJvhK\n"
+"AaUqBrWA41vnjKOtJudTsZLfufKafzYwVonze7fXGyVsBRjVwHNS4iqq2QIDAQAB\n"
+"AoGAJCoStI6R3RXUKvKb0GATuTJFZ50WBTmCPTK9FMkwdCuY47vPy2Ky7y3cUMTI\n"
+"urf5PewrYs0H72CFyWGMXkKVi8aOYshsATEXMfGSqOcqXn+UDssRzvabZFlpnAUa\n"
+"WDVt/iN092AdakXNna7/DxrLisDpq8HHJfjtlWGPfkXRg4ECQQDpHeKimTvwJcPc\n"
+"iDa6Qb/n9gwLeRckfzhYtfX1luJYLIOHh+J9vjQN75thenBLQB/B6qlKtOn9ejxg\n"
+"5z+3zIOpAkEA2JbxXVTCOA802p9khvHxDtLHdKi3w/BjjJiC7Mgqo69ZI+s3PB9E\n"
+"F2HJA69kZqpGqvybWHDapjWsq7rcMlxrsQJBAME2yvR3y00VEAyGPc4M1vF8ZqlP\n"
+"uRW/+ETWtEDUyU/JvU6lGt2bu2tdkEyv/cjxIiFIzP4litdT7B1pLc+6S9kCQBwE\n"
+"usiWFGHoJbA6emiyl7qRLdg7kzo3uMkRWa6D3nA6WM+6t/SBHu/faH+fit91G5s2\n"
+"/mmcf8yMmP/GNoIVTqECQFl4Pt6yGiz/YVoYSp35ljY5n3JB6T8o2pOmIrRLuPmT\n"
+"6kgyygtJBAmx5nnQoeG8n08tl9QakWznKzkNJ0DIFKI=\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXQIBAAKBgQDCaOqJ0lsSAEBcnNB6X7BvVcEcol+evi/nJsPe0uT1SbtW50Ch\n"
+"vYOHwK6aQR2C5x9VSs47cLynTL7tNt5d8oeryF3NpI8VTPLImDJCcvUZhS7p4bxn\n"
+"JO+Wm+D/e3TWfyjreuWtdL+Mfimw2gzwWuBEtmj51GzQ89eYm7fh11SB6QIDAQAB\n"
+"AoGAWaakMbZNxPlUtOCjyysBY/Y5vYira7rswD3CKak7aFn+CE9QIMYSN7IFUqEg\n"
+"iNMoQd7jR8nvVX8wtJeO5+gF48W13C3n8FZSrW7c5N3bmfMIgo0xa/TGfeXHP98o\n"
+"7vhH0I58j3ZZt0Q+3wTm7t7WPE/nJzgrCk30TqmoaEmstTkCQQDtV6YZ6juEK2Lp\n"
+"LGUiqohcS/WJxvFrF5+LNpk86Xdgomf6FphZlkq42KYkvl7qibKDcfDqLKTbHHle\n"
+"vQQeCgZ7AkEA0bFHi7F8o4iHtKleBvt4QCj1neA0q3CRDypCI5EqFSrNpxY4Krhh\n"
+"WYSVX+xT00QYaCpKKWfYQztCw7Anylv96wJACl86Mwe5ch0zRV1bThiFvQLUyCCZ\n"
+"jESMBFlueOr6/I4cXSF/puqaeVl+aTyoiTdbRcNE8/bffXPRGgLIm0d04QJBAJSY\n"
+"lmTN789Lby99Xh6AkaSV4ghw26Ip8QHYJmph8npxjK69Niw/4Oy44cnKBVUPSmR2\n"
+"o3tYFY7/Lb7S1D+4lOUCQQDbMQUGVsZT+ZjuOG1bAjIuXoAOfOd3mgH5VgQHjSgJ\n"
+"ourZtlJ4OUpNrq9IfWqPkM+zSE8+0Dk8/9MS5ngBA/SJ\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIICXQIBAAKBgQDNbHjwg+7tVNr9erMLowXRnIcttp4pUJbr3B7Jo/u+kD/Yo3F3\n"
+"4rIKhHpJl1uEHP1QmvAD+4ApFFI2hNG54xYI8dGflxL5HOs5xxyOPpkrwzQ8Qvnv\n"
+"LPg7Gf6PAW9zF4McG4wK0TkrV28G6NhqcPs5VFY6UyvfZ0fEdWAeoWTIfQIDAQAB\n"
+"AoGBAKOmkMp7MLLd8QAS6eSRYSdWHdLrMyES1MjduaFGBF4SKOr7en/Zl6ENXSaX\n"
+"cA7V0XCPnjpt9/HCAKTyNupx4LCeFWiqdu8VGXhlzX8bdb896OSR2brKbxgRY5tF\n"
+"36uL8akrZdrYgocykQCxmRARMB7/rHwDusiamjL6RUZ3+c45AkEA6UPTVmKZQRMr\n"
+"A7Qgg5nXrXo9117Lpqf3FdZ1wdni9V59Ptf5xrx9oGZNZzctJPXSAH4M4cumSJrV\n"
+"sZ1V8qE7AwJBAOFx+5luLrVKrdlG7MyOhTAdhKYUvKIvL4wvVSY6y+L2nNEx/cTx\n"
+"KYbxGC+H1RJbkCS09rYir3VfDRWQ3W1c1n8CQH+X4hn2hO3blkPIW6CgniD+JKWR\n"
+"7MOUTMtdK7yFemfM76VYbgAPSohabSxwOfllnSE30cQQqTw9tXYaIdE98BECQG+M\n"
+"QWxSS0QillB6unIgVqBPCrJOcmNhK4qWZPBMiVNcqI0Nyj2nAeAl7MyfzfqOWY0A\n"
+"CU5nbR+LD2NLUXRqSisCQQCN3IGv1WOWInmA5xhU6vCFDX5u48Dcji7VLJO/Nv/i\n"
+"b/zHKAgjHk5Js7bi5ZWEGaUgA4Jt6cKmGdERheqTMKxx\n"
+"-----END RSA PRIVATE KEY-----\n"
+};
+
+static const char *PREGEN_KEYS_2048[] = {
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIIEpAIBAAKCAQEAoksI1qIuIaFCqT4QbgDvOQCmr9Z9F0E7ku+U5Ep/5dWNANqB\n"
+"bSzAOq0+cxiisfF+H4desoqiWDUwlOwXH74qD3ZsbChhvFUD78cQBWQkF+whLVHb\n"
+"296QmF0LZqosqz9HMS9CdoMUc1brZb78Hb25QIOOjrg25KYHLZHaqcet1wfhHow6\n"
+"Uehc6QTuWgOWFhJnfiXzYgen2o8lnLixxZozhk7Lm7Aix9ur2ckXdQ2Wgny4xw70\n"
+"JW84Hapnd8oFUD98XXrExk4VFuIcA8qo7r7y18II6wx4Cw1suKru6bhW65cM/y51\n"
+"KC4lB7VkvuoJCelRFdM1PfKZLv2tJP63oAqJrQIDAQABAoIBAQCWc38PEqw3avqU\n"
+"UMAEaoNa0bq1Gd8/Nq8WqVnbRSFKHO2pk+cWIb1W6BITuwvgcGKesezdEV4s7apK\n"
+"9I7/U1hEm2Ep50mrwRh0KZM1nD9Fmharn851Bt//D4qpMytT2caS1yADI8NKpZJ1\n"
+"8VZh7+cT4qG+txHUaAIRgbw3VrBWvTIMu6SOSOZm+e3eOr5UU3du1KvjdJHJ2c2k\n"
+"TceHvUdKxV7OYt+BBSN1oBOhs3ajUSRge1v3twRDg3cmbwG0DeXvwHNhGUTcF8IH\n"
+"JO1RF5njbkFvyqdAi3ltjU41zYd4OMuPtrwzFOtxUjKT62Soz109HUXXE2CGKFPZ\n"
+"PVi5/BIhAoGBANN1xqS5BgHszIB0nXbw5ImYpTRmyhO0KsTblBT9+8Q/B7BCK7bM\n"
+"zl+dOPeyvEadSwE7RSMMt6CAlTakWIf3Quw/VZajvXy9C9/LHf52pEKXjxMFMPKE\n"
+"aGLHpQnwMtDi8/H8AEAXxI3hpxB2KVR7sAYHWihSGjRJ6oPGvEmKEkb5AoGBAMR6\n"
+"G2PKz0xk1vFrjfjSY+y13gH/t7xHaXUggjggUSGKaknQh2BDUllXjadeI0fi1eLW\n"
+"r98ZImZZgntAgjaIZ4bAlooTDk4gRHaz9jI+z8lsRwOKnWdiigM7txiXZTMVwMqj\n"
+"o5mMNGMA+A+ACkTViRHmkDI7S/9FqAvnbOqVwgFVAoGBALUcY6WDvwx5B3Jh7tgH\n"
+"XIYpEh3+h8c2gYcX1g3gtvkPTwN8uToY0gz8eOVV1YHZiHsmi4GIi+HRH3usaRMT\n"
+"COOVHzYlSc8Dj57+tdLTRL6wVl9hC9o647ju64DGlI9qQquYPZKniLZIdbFYsu9j\n"
+"/JA9Tc/I+h6czFpPJccKlbrpAoGAAPWXrKUQ3g6f/g3IY66jTkSVEO1uuDyhBzFh\n"
+"cWS3ALLsUe/yuUWa4VTMHEUZZwB0iucBdNVqlZVaTb/C4wFHgCDwmzv8leUScIHw\n"
+"cc5ctV8R+bJzkk2o3tsrybLzi4xPpK2n3tgQaWtXyruVUUC5qpy1l4kylcyBRY2b\n"
+"uomAqQECgYAiCNWtuWIDlRBcvtIB+kHguzcoFT3vTCCNhalTEn0zi/tbi+voQgVJ\n"
+"SDJNptZv+6vRwQ/HfcQtljKIPO6hUZPYaFWRNhgbh7Ay85lRXYXQOottE8ayReBk\n"
+"zZb0fl853Qah4DPsaOugAvhjjKeBmKg6bFWO1z6hj18I3UpDf2YnVQ==\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIIEpQIBAAKCAQEAssO0r37mSJNAkc/ISwXBsu9JjyLeWlsHPAhylQGkSAdp2rjz\n"
+"E6AT0Eh3wrocNO31I4pvHReAuh1QedGY6T1cQwO/WAAhQtRCBQDK12qWRgfbC11y\n"
+"Xu7zNYPd1Z7YIRy+FxhbL5f+lv3rEUv0HUG5c3CWhLtbANKg+jOieIDzA4Yp1s55\n"
+"ynodQBUkTZrwQiT0P8yDSjiasf+clgJRfA1k2XK12KSAMRgyDuPTE4OtBxBvUM3L\n"
+"Zvxs81PsmcOuAG4DLaFTg2a/QkCjt2VC1SYYuh/LVxpL41FFh3eMoK5g5deHkgRe\n"
+"tlywKjAHIDJu/qgNzNgNW7ymwn2CfBvry9h0/wIDAQABAoIBAEMZ4wDdCWPEokAZ\n"
+"Vn2Ss5qO53WrCPuxn42RPjFgZGIFJl7LfbKoK8fK6+lUIrJbf+DPXdX1tIQn7MVN\n"
+"P7CNL8yX44MMyW9kbUOjgIBLqgyvdjFV6lBoMTKtRN+iuE31lATnR5Md4pqaxVnA\n"
+"wOkaepoycM1x5j7w0SwZparF/HIdkYv0y/MysqT9ByupPA4Fqp/iRSrosHXahNtI\n"
+"KZYj1TyERYtuDXq91P4dr/pWq3FmDNI8O3upblkL0YouvG/ZlFLdiNy77XbAyWcX\n"
+"ps3YDddM+vECnXO3+sa3ZxgBYvXJdWrrIzM5A+jCkDRZQGsFAzK5I5/S7C2ljt6i\n"
+"SmzqvMECgYEA16bGy2XTi6KBPb8aev/OBgK9XuGLwUqK1m15mS9Y2qPHmuc22qaZ\n"
+"hw6zginPFrxAEtQWKanhZy4aVqlLkDPLwRnyeuMo1EZAc5B1gZ5ViSAKxBq99hA9\n"
+"eqyakdb+IUQsEnRDxSc2gqUQ0EagksUyw5wGG5Q/CVEALmS/r1SU3KUCgYEA1DYf\n"
+"6JYdzuRtule3vYeWXKf8sOJpdplgWV7tvLrKkQhdE564uwMCYB23HvYfwWqEdDYG\n"
+"fsYg/ur/stk9MDZ3wZKffTEM8V3sX1t1JXnC3ogSAgMGhLZ3ILOLqkoO4BEZJnsS\n"
+"dMdiNijlAtQkqs/BO/UVUAKysCtKP3v/+1775dMCgYEAvLjGFjApfnSbV/cK7IM6\n"
+"wEXbhdIqZOCgOeEaXjVyM/zKbMRVW+oaR3hVHd8KzSG3jQKv1oxFpu9Qu3ByoWLC\n"
+"uF3Ft0debs6ADuJoAyQWROeWpGGmxlUWCGpO5rxYL7KiQxAeUsXrTU+5NBvq4CbV\n"
+"MxwyuCX3OGb7mp4upfiGQcUCgYEAuhVsDYv1P4LXJVvd5viKRV2ZG5KuYC1Ga5fu\n"
+"aFxzXJI07At2eaa94oKsHR494mEBHNZzA5/BN0fiSHZuTWS1xqxH5oOokc6Gg2ez\n"
+"ZdVLp88x20nD4YQPGkHW6tBeEuVrZG7vVC+yU0Ow7bYRISdkjqrusWZsQkbzqI+X\n"
+"fFliEbkCgYEAu8x+47M1ordbI7NmbBGyiyP0r7nMRCZ+KEvGeCNYracWmsnCNnfV\n"
+"zR2UzmwtSainw3Ho8Jv/rWDC8RIDauyBRYEi2VqOnUzT2ca0iymQyLeBCudAQuio\n"
+"drOu4JU8RzZ3Ad6V3DNFnaqmX/7GA9Pa2GI8NJMyb8p1GAGv7Gi8nxc=\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIIEowIBAAKCAQEAt01S8JuEwWy/Hzb90yO2O7oGWq3GfvfDpFOF4OQnwG3kQ/BP\n"
+"4MoPDCYHdqb3iI9aD3vykZA6Q8zpdfGwjm4+bHrgRdiSmZWv8NvRwuQ5Ji9xbiGn\n"
+"hA1XwqH9hvgFTiy6tRvirWSJ7kzH3Q/bEGpCbHUQkwMog4v6yCNKNrjlwjN++eCi\n"
+"gFK/0RMOJMLOs8BD3zY+lKjd/pd8LBRujkMyUF5SryeRueAFjD2sq4OXq8DPABGt\n"
+"zdR6vbTcsi4JwP1Q6y4x0/LIWEprzzewNU63I5E2zj0WnoRGAIM4aF+VuqcHjWUx\n"
+"VWnyLZldSen6lScZ4xj4seitiDbSFvtFkDF6VwIDAQABAoIBAGTP9im2ntDyyjqU\n"
+"uA0DuxomOZBtupniEouyFBOX5/UBe2WSKZxsBNKdp8UuFz3X+aRCeyprtF/NtyjT\n"
+"AFOVdmebPPWtIxOtK9LAUyFo+7VwqmXzxHnwDLBS/2jXx7MzDozFBWpvvRx+xf1i\n"
+"1wy0JEwaJj90oTeYKRkhr5NhJZwkX8zCNYaemBd3kHB3aGWGJasI1Y81UezeRKCn\n"
+"hSbn2CrWalI7pyJ4lsavM11nIq1Eu2ZthJiNCMghbYrHoBHd+iVWiCYchP2rNEWV\n"
+"sdHtaVHtQ9zdZ43bao3OzPu7lAjd6UAbxsuhUe+a2YdDz/+Up+6+BvQf1FCfYIjW\n"
+"KFUdCoECgYEA4t5O+u0V9gkMUhKsevYb0zgc7O/mo8ivN+V++EpAtL0mhiwxeO8p\n"
+"oef0szLyhdULQeLN9pJQDCeAbkGdwIe3L+AKU8o8BFGEWLFysZjMg9In/UTrp5MN\n"
+"mMDy2SRKKu5BqsvdYH302xpZfHq1T2cMNDWE8lrZffduH06Cgq/XEtECgYEAztbj\n"
+"bhFneADnrvk609VnOQvoQEjySeCQKFQFRRI6k/FguqMisL2IRXnMaWammosdeCAg\n"
+"m7eZchnszHIst9cwZUKXUFqmAqeDuWSNdTI7uKZH6nT/A6IDlgdjaHsqhvpK0Ac9\n"
+"ngycdHONitOZh0ZG74pdWjf828Dwzf+CuYjl9KcCgYEAmIvI6ZqvkJ8m5Kzfw1Jn\n"
+"BVCOypbJK8oOX3R2Orea6KzjEYb3wQx3nwFcHX6danYFOskpmqlpH7MT/Y8rZsEa\n"
+"4RsxdoPedTzm08iFiXtn0R9nejp0hlov402iPXXUVSedih3IflBTa1w9XaEY9wog\n"
+"P57ZBSknYzcTmgNtaDiaUnECgYA5sWauhNw/dMEq5QmrnJK2LsQRakdqo+CR3x25\n"
+"LmR4b5Nze51pfvRLrLV/kMpXwQXvQ8bUqFl8og6S2CXxAWzWUcSy/RXhF6h+RbXP\n"
+"Qru1vWvB0fBvqvklF9p6giBSle3YKKzfMNVTBggs+OiR+uA+YHG5gHRfN2nzi5mC\n"
+"9tRtcQKBgBnDSi4lRCjRe9pPnyAYaa4iyBUGhjPysScSLY9orel89+qmTBQ/Py6J\n"
+"0+sefL4ZJaOsuaR2mSSPP/lbSkF9DMFs4tHbBqY+WkVNYLshAkauHwqv26HTVCSd\n"
+"QKzeb7uZw9lNaRIzDvy/3wfCLvXfdDozPFrOUgkyaBN5pJSA/4sv\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIIEogIBAAKCAQEA9qtiDoJWqU/eSlpj381eG6UcDzfMguFh/q4e4s7QVdRYj5J0\n"
+"Msv0PCkti8JHuvQUyncRpOPccBkhNbVjNbjIgw1pHaIZNdVotUDhP0kseRyJ6z3M\n"
+"qbZ5qKn+0mHjVjPNItVDDe6tebYMT1BZpVyRrCOqY2v5z1ecLC+ReygmHgDpzg+L\n"
+"0rWfIxGT10IPZ8pAlcdEn6xt5aEhi7mPCX/xwqfQChPIJz6zVLEC8UaPtvDBohPR\n"
+"6NQTBTeZZAAtzrQ7+oNxfz1v6Fz6RwMei7Q+qOBnMiwpQmbcDBKABM2RnXSpD0LA\n"
+"1GR7/+CiV1HQoShWVvEwrSIlM6jVAJo6iqF6WQIDAQABAoIBAHqwcdxPnfUm4aTP\n"
+"4r9NcZKEhDlZgqJSoiA/0OL1BRC7xrTanmspoLhPrvTF1FG715+Aq8j9AQbMqQUC\n"
+"zG7LEwiEIhV4K9vn4uXMeHy206UFud/E5EhBl695pmJUB/Q3XcAGnQyP+77++o50\n"
+"o7IpIdeiAbzj1uP3aplbq5u7M4JV7fUZWA/368G4HolqFTxcAfBJ05GXlp97BBwY\n"
+"AnY3/pNrKMz0NiPf3nsJHYWK18up0JCLPL3tomc94wuNZ66spIazHIL9aaKY0q3V\n"
+"LkBrelndfYM1m4xRTnSOy6STu0qKTPOpX0C8XBLYs6uiXjRsChqSYwndCCeASaH3\n"
+"LGNIcbUCgYEA/m4qvt8tdT4wEvnE+QUxEELmBtT4UFa3NnQISrzNlhNeI0Zd2xlp\n"
+"SG0/pcw83mG2uX+V5xSaWL5LYfLBkvy83Y0yIWgYbbIkyyCOUZnTpwaDGU/FjWip\n"
+"3TfXf5qpAgiez94sV+MsFpKfG05yxJh5u+3sIyGTVUAxp0HPx4LVgbMCgYEA+DD1\n"
+"fu6ttpuV1UMrsFdjuk6gBvSbyJ9OilY2jT+yE7hSRc/yP3O9ikuR74tNlVrWTnO2\n"
+"0kcYbyLJXE2cGUC2q5e4r8TDGiozNfQ7/OC2M3XaJ+xJk4zMf/8PuDDpWr+18ZXA\n"
+"Pf+ibXWTFvZ6ZeUmpbrrfCrXdvmIZnwVuOI0FcMCgYAZn26emksxq3mb75tumJ9A\n"
+"S/xuY7Q+Iv2Adl7/Z9QscPbiBowdLIn1yUrHn7Hhk2WbeMXX57NDjKZ6zr+/1cQP\n"
+"a9DInHsZUP9zlWu/vAYcpAM/4VC71PaGWMFTEHhExCl6NZ2xnCcsfseXMGdOdSyN\n"
+"SICnaRI1W6mkdnQ+W2a1EQKBgGEKA3KVr6XuPy8bDEHuaTe29irCCQbwAq1j+ABS\n"
+"HzZGoyRYocbdYgZoda7LMJJs6c3SwHCHC66oU0KbtaTKAKImuDdBH2djiJJX4/yD\n"
+"f7mvIpTpdfsS2gJRn7vMo/CvdFv4ySl0gfV6OwCHbmPYrLuv0dLCjWwfNI2dhoC7\n"
+"MNIxAoGAIPSIG4BrShzbeX4c2L18iwIg+NlOcUbtl0Ccr1t6uLGI+ge/6I6T/5XH\n"
+"DPKqYIf0IRYV8suxpfQNKiz/C0NPffA1d1M2hvuAg2v09o2cSwvdcQwdmakKZ5bl\n"
+"sdCuYKdCIwomEUOz/4XgQrJl4XDUqxftJT6/egAjWvcIYvfNCsY=\n"
+"-----END RSA PRIVATE KEY-----\n",
+
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIIEowIBAAKCAQEA1yHZMsgRLckL+v6rgpGq9qmxVBNDxeuul1V/QlFyOlcAk5n/\n"
+"uduTalSqGQhc4NEePMxq6nFui4ucpkZOozmcEnhV0N9jld9IB9rLGt4erdg7RKl9\n"
+"+gQ+zTn69j69U36E2I47H4dM69uxeSOyWP2Odxpw+biisa3o8mMz1zCmuj4GMDtG\n"
+"DlnSpthFzgQR6N1pbvxLXrWg5F16GqFiJOD7kXDfy4/l6kB/mDs1T/3r8kav6DqR\n"
+"c/t3aQZxgWGIpI7hc9Qgvp7coZRMey5dNOZEna3tqS8dn2tZlhkpYV5uyFUjmxjG\n"
+"TERSULQ7hvUqW+eshGGsnxFtL7ANnTSc4xECowIDAQABAoIBAFhJJMhpQFuIySjd\n"
+"AGeZ/g4x/3rgWQzNNp4WUR5XLEhy0eLA7ShJywp06kVRoEQGraEHxsyldldAGS5H\n"
+"ZhgoGTufNKB+PHER646FpJpHE1IGjfQUloVW3qr8I1iQ0MOGBWCVpf+/V7rnMsLi\n"
+"+lr421FXgYuJ0QKXuyRVv72M0q9U6i+ml3aVAhgW/19oFg+dW7YccX+9iVyD05Q5\n"
+"KR64tX8xd4wrAqfAgYA3erbbE6GTyHYD5K54kIgfRr/+pIU4qc1L7XOCblnqc/rI\n"
+"BilFysEC634r2MNe66uQvNui4oQTfBcFFlXg0zAmp7d5QE0ApOL6HpCsmbImm2uJ\n"
+"sdFNYyECgYEA716kfEv7HfnF0P3pAP2AOuEsW6t8q0UtWvnHrwRQXQw8Yv90g7kD\n"
+"pUV3/BjD9VQgsQZosbdSn5wbT4j7dypRdrzYk+8m/hBk4Q8M/tWoRGVOn46NudvK\n"
+"/KX0A4ODLuulj8yAZVc7CM5Cdy4GCGJBVO+oVvBUAnHxfZziOyqBw9MCgYEA5hQg\n"
+"HEORzdxvbbfAx1ggvH1Eg1lqRhmpI43PpRkaoqb8jLwXb2CyBeuv3RBft/X2Tr6F\n"
+"mHpe0U1kN/5YEjii/Q/jUX8azIHaUNNSAjrriEeMQZOqFxmhCdiyeXuqg2fbFbhe\n"
+"K3Q6/fsB1xj9OOSwyPMqm/M5U0LsoGjmg8TFE/ECgYAlImKUIdlwOgp1NJ7MF4eo\n"
+"Gryd8AmkLFQv8+YFgb7R4I8RsJ2rva0SG6fUhScJTSbRL7RYNZ9swXP/L7oLL5Z5\n"
+"vCxBLu22pmZv/7y9X/n9ulWrLRtRhQaFkV08mk9knQwPNeOJVTIEWLM49/vZmxyV\n"
+"h6Ru8FOoGXMkUI1MLnj5HwKBgGJLkNhiacVYeuaWDa9c0EeXARFYvxWJ2wAMkvzG\n"
+"9+ErlFQP+7ciyYvMAItidnJii8NilDLrfNzQwpNFf5zxQ3j4M7bapblfdMT5M10u\n"
+"jPfhEWPm0VEjKvDI+p76HYQcd7YU2W6ZLqbZeRTLYUvQMFL5yGduBzyyJ+P0TR9Y\n"
+"jpYRAoGBAM7vYGTprw4w2tTZPFICXVk1bQ0LO06oNRtwkiQTUT6UqPjWMFyvHnmN\n"
+"11SVVBmRZ0RAk6e5eZLFX8WelJ4J4nSOGRcJheCtoEFlO7D1ewAUSbqWJ0pBqp2T\n"
+"gV4oCS8LYe8zReVoYZJjuLwoHvxZzs/hUjc3SI2HRW2W/HQRPC25\n"
+"-----END RSA PRIVATE KEY-----\n"
+};
+
+#define N_PREGEN_KEYS_1024 ARRAY_LENGTH(PREGEN_KEYS_1024)
+static crypto_pk_t *pregen_keys_1024[N_PREGEN_KEYS_1024];
+static int next_key_idx_1024;
+#define N_PREGEN_KEYS_2048 ARRAY_LENGTH(PREGEN_KEYS_2048)
+static crypto_pk_t *pregen_keys_2048[N_PREGEN_KEYS_2048];
+static int next_key_idx_2048;
+#endif
+
+/** Generate and return a new keypair for use in unit tests. If we're using
+ * the key cache optimization, we might reuse keys. "idx" is ignored.
+ * Our only guarantee is that we won't reuse a key till this function has been
+ * called several times. The order in which keys are returned is slightly
+ * randomized, so that tests that depend on a particular order will not be
+ * reliable. */
+static crypto_pk_t *
+pk_generate_internal(int bits)
+{
+ tor_assert(bits == 2048 || bits == 1024);
+
+#ifdef USE_PREGENERATED_RSA_KEYS
+ int *idxp;
+ int n_pregen;
+ crypto_pk_t **pregen_array;
+ if (bits == 2048) {
+ idxp = &next_key_idx_2048;
+ n_pregen = N_PREGEN_KEYS_2048;
+ pregen_array = pregen_keys_2048;
+ } else {
+ idxp = &next_key_idx_1024;
+ n_pregen = N_PREGEN_KEYS_1024;
+ pregen_array = pregen_keys_1024;
+ }
+ /* Either skip 1 or 2 keys. */
+ *idxp += crypto_rand_int_range(1,3);
+ *idxp %= n_pregen;
+ return crypto_pk_dup_key(pregen_array[*idxp]);
+#else
+ crypto_pk_t *result;
+ int res;
+ result = crypto_pk_new();
+ res = crypto_pk_generate_key_with_bits__real(result, bits);
+ tor_assert(!res);
+ return result;
+#endif
+}
+
+crypto_pk_t *
+pk_generate(int idx)
+{
+ (void) idx;
+ return pk_generate_internal(1024);
+}
+
+#ifdef USE_PREGENERATED_RSA_KEYS
+static int
+crypto_pk_generate_key_with_bits__get_cached(crypto_pk_t *env, int bits)
+{
+ if (bits == 1024 || bits == 2048) {
+ crypto_pk_t *newkey = pk_generate_internal(bits);
+ crypto_pk_assign_(env, newkey);
+ crypto_pk_free(newkey);
+ } else {
+ return crypto_pk_generate_key_with_bits__real(env, bits);
+ }
+ return 0;
+}
+#endif
+
+/** Free all storage used for the cached key optimization. */
+void
+free_pregenerated_keys(void)
+{
+#ifdef USE_PREGENERATED_RSA_KEYS
+ unsigned idx;
+ for (idx = 0; idx < N_PREGEN_KEYS_1024; ++idx) {
+ if (pregen_keys_1024[idx]) {
+ crypto_pk_free(pregen_keys_1024[idx]);
+ pregen_keys_1024[idx] = NULL;
+ }
+ }
+ for (idx = 0; idx < N_PREGEN_KEYS_2048; ++idx) {
+ if (pregen_keys_2048[idx]) {
+ crypto_pk_free(pregen_keys_2048[idx]);
+ pregen_keys_2048[idx] = NULL;
+ }
+ }
+#endif
+}
+
+void
+init_pregenerated_keys(void)
+{
+#ifdef USE_PREGENERATED_RSA_KEYS
+ const char *s;
+ crypto_pk_t *pk;
+ unsigned i;
+ for (i = 0; i < N_PREGEN_KEYS_1024; ++i) {
+ pk = pregen_keys_1024[i] = crypto_pk_new();
+ s = PREGEN_KEYS_1024[i];
+ int r = crypto_pk_read_private_key_from_string(pk, s, strlen(s));
+ tor_assert(r == 0);
+ }
+ for (i = 0; i < N_PREGEN_KEYS_2048; ++i) {
+ pk = pregen_keys_2048[i] = crypto_pk_new();
+ s = PREGEN_KEYS_2048[i];
+ int r = crypto_pk_read_private_key_from_string(pk, s, strlen(s));
+ tor_assert(r == 0);
+ }
+
+ MOCK(crypto_pk_generate_key_with_bits,
+ crypto_pk_generate_key_with_bits__get_cached);
+#endif
+}
1
0