mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
r16411@catbus: nickm | 2007-11-05 11:27:37 -0500
Remember X509 certificates in the context. Store peer/self certificate digests in handshake state. svn:r12382
This commit is contained in:
parent
22c31d91ab
commit
ea1bea5830
2
doc/TODO
2
doc/TODO
@ -43,6 +43,7 @@ Things we'd like to do in 0.2.0.x:
|
||||
connection.
|
||||
- LINK_AUTH cells
|
||||
- Code to generate
|
||||
o Remember certificate digests from TLS
|
||||
- Code to parse and check
|
||||
- Unit tests
|
||||
- Revised handshake: TLS
|
||||
@ -57,6 +58,7 @@ Things we'd like to do in 0.2.0.x:
|
||||
- After we send NETINFO, send CERT and LINK_AUTH if needed.
|
||||
- Once we get a good LINK_AUTH, the connection is OPEN.
|
||||
- Ban most cell types on a non-OPEN connection.
|
||||
- Make code work right wrt TLS context rotation.
|
||||
- NETINFO fallout
|
||||
- Don't extend a circuit over a noncanonical connection with
|
||||
mismatched address.
|
||||
|
@ -44,6 +44,8 @@ const char tortls_c_id[] =
|
||||
/** Structure holding the TLS state for a single connection. */
|
||||
typedef struct tor_tls_context_t {
|
||||
SSL_CTX *ctx;
|
||||
X509 *my_cert;
|
||||
X509 *my_id_cert;
|
||||
} tor_tls_context_t;
|
||||
|
||||
/** Holds a SSL object and its associated data. Members are only
|
||||
@ -64,6 +66,7 @@ struct tor_tls_t {
|
||||
unsigned long last_read_count;
|
||||
};
|
||||
|
||||
static void tor_tls_context_free(tor_tls_context_t *ctx);
|
||||
static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
|
||||
crypto_pk_env_t *rsa_sign,
|
||||
const char *cname,
|
||||
@ -211,8 +214,7 @@ void
|
||||
tor_tls_free_all(void)
|
||||
{
|
||||
if (global_tls_context) {
|
||||
SSL_CTX_free(global_tls_context->ctx);
|
||||
tor_free(global_tls_context);
|
||||
tor_tls_context_free(global_tls_context);
|
||||
global_tls_context = NULL;
|
||||
}
|
||||
}
|
||||
@ -341,6 +343,16 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa,
|
||||
#error "Tor requires OpenSSL version 0.9.7 or later, for AES support."
|
||||
#endif
|
||||
|
||||
/** DOCDOC */
|
||||
static void
|
||||
tor_tls_context_free(tor_tls_context_t *ctx)
|
||||
{
|
||||
SSL_CTX_free(ctx->ctx);
|
||||
X509_free(ctx->my_cert);
|
||||
X509_free(ctx->my_id_cert);
|
||||
tor_free(ctx);
|
||||
}
|
||||
|
||||
/** 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, and <b>nickname</b> set to the nickname to use.
|
||||
@ -382,6 +394,9 @@ tor_tls_context_new(crypto_pk_env_t *identity, const char *nickname,
|
||||
}
|
||||
|
||||
result = tor_malloc_zero(sizeof(tor_tls_context_t));
|
||||
result->my_cert = X509_dup(cert);
|
||||
result->my_id_cert = X509_dup(idcert);
|
||||
|
||||
#ifdef EVERYONE_HAS_AES
|
||||
/* Tell OpenSSL to only use TLS1 */
|
||||
if (!(result->ctx = SSL_CTX_new(TLSv1_method())))
|
||||
@ -431,8 +446,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, const char *nickname,
|
||||
if (global_tls_context) {
|
||||
/* This is safe even if there are open connections: OpenSSL does
|
||||
* reference counting with SSL and SSL_CTX objects. */
|
||||
SSL_CTX_free(global_tls_context->ctx);
|
||||
tor_free(global_tls_context);
|
||||
tor_tls_context_free(global_tls_context);
|
||||
}
|
||||
global_tls_context = result;
|
||||
if (rsa)
|
||||
@ -679,6 +693,29 @@ tor_tls_peer_has_cert(tor_tls_t *tls)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
int
|
||||
tor_tls_get_cert_digests(tor_tls_t *tls,
|
||||
char *my_digest_out,
|
||||
char *peer_digest_out)
|
||||
{
|
||||
X509 *cert;
|
||||
unsigned int len;
|
||||
cert = SSL_get_certificate(tls->ssl);
|
||||
if (cert) {
|
||||
X509_digest(cert, EVP_sha1(), (unsigned char*)my_digest_out, &len);
|
||||
if (len != DIGEST_LEN)
|
||||
return -1;
|
||||
}
|
||||
cert = SSL_get_peer_certificate(tls->ssl);
|
||||
if (cert) {
|
||||
X509_digest(cert, EVP_sha1(), (unsigned char*)peer_digest_out, &len);
|
||||
if (len != DIGEST_LEN)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Warn that a certificate lifetime extends through a certain range. */
|
||||
static void
|
||||
log_cert_lifetime(X509 *cert, const char *problem)
|
||||
@ -736,7 +773,7 @@ log_cert_lifetime(X509 *cert, const char *problem)
|
||||
* 0. Else, return -1 and log complaints with log-level <b>severity</b>.
|
||||
*/
|
||||
int
|
||||
tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_env_t **identity_key)
|
||||
tor_tls_verify_v1(int severity, tor_tls_t *tls, crypto_pk_env_t **identity_key)
|
||||
{
|
||||
X509 *cert = NULL, *id_cert = NULL;
|
||||
STACK_OF(X509) *chain = NULL;
|
||||
@ -932,4 +969,3 @@ tor_tls_hmac_with_master_secret(tor_tls_t *tls, char *hmac_out,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -53,9 +53,10 @@ tor_tls_t *tor_tls_new(int sock, int is_server);
|
||||
int tor_tls_is_server(tor_tls_t *tls);
|
||||
void tor_tls_free(tor_tls_t *tls);
|
||||
int tor_tls_peer_has_cert(tor_tls_t *tls);
|
||||
int tor_tls_get_peer_cert_nickname(int severity, tor_tls_t *tls,
|
||||
char *buf, size_t buflen);
|
||||
int tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_env_t **identity);
|
||||
int tor_tls_get_cert_digests(tor_tls_t *tls, char *my_digest_out,
|
||||
char *peer_digest_out);
|
||||
int tor_tls_verify_v1(int severity, tor_tls_t *tls,
|
||||
crypto_pk_env_t **identity);
|
||||
int tor_tls_check_lifetime(tor_tls_t *tls, int tolerance);
|
||||
int tor_tls_read(tor_tls_t *tls, char *cp, size_t len);
|
||||
int tor_tls_write(tor_tls_t *tls, const char *cp, size_t n);
|
||||
|
@ -17,6 +17,8 @@ const char connection_or_c_id[] =
|
||||
static int connection_tls_finish_handshake(or_connection_t *conn);
|
||||
static int connection_or_process_cells_from_inbuf(or_connection_t *conn);
|
||||
static int connection_or_send_versions(or_connection_t *conn);
|
||||
static int connection_init_or_handshake_state(or_connection_t *conn,
|
||||
int started_here);
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
@ -629,8 +631,8 @@ connection_or_check_valid_handshake(or_connection_t *conn, int started_here,
|
||||
check_no_tls_errors();
|
||||
|
||||
if (has_cert) {
|
||||
int v = tor_tls_verify(started_here?severity:LOG_INFO,
|
||||
conn->tls, &identity_rcvd);
|
||||
int v = tor_tls_verify_v1(started_here?severity:LOG_INFO,
|
||||
conn->tls, &identity_rcvd);
|
||||
if (started_here && v<0) {
|
||||
log_fn(severity,LD_OR,"Tried connecting to router at %s:%d: It"
|
||||
" has a cert but it's invalid. Closing.",
|
||||
@ -725,10 +727,11 @@ connection_tls_finish_handshake(or_connection_t *conn)
|
||||
int started_here = connection_or_nonopen_was_started_here(conn);
|
||||
|
||||
log_debug(LD_OR,"tls handshake done. verifying.");
|
||||
/* V1 only XXXX020 */
|
||||
if (connection_or_check_valid_handshake(conn, started_here, digest_rcvd) < 0)
|
||||
return -1;
|
||||
|
||||
if (!started_here) { /* V1 only XXX020 */
|
||||
if (!started_here) { /* V1 only XXXX020 */
|
||||
connection_or_init_conn_from_address(conn,conn->_base.addr,
|
||||
conn->_base.port, digest_rcvd, 0);
|
||||
}
|
||||
@ -740,16 +743,36 @@ connection_tls_finish_handshake(or_connection_t *conn)
|
||||
return connection_or_set_state_open(conn);
|
||||
} else {
|
||||
conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING;
|
||||
conn->handshake_state = tor_malloc_zero(sizeof(or_handshake_state_t));
|
||||
conn->handshake_state->started_here = started_here ? 1 : 0;
|
||||
if (tor_tls_get_random_values(conn->tls,
|
||||
conn->handshake_state->client_random,
|
||||
conn->handshake_state->server_random) < 0)
|
||||
if (connection_init_or_handshake_state(conn, started_here) < 0)
|
||||
return -1;
|
||||
return connection_or_send_versions(conn);
|
||||
}
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
static int
|
||||
connection_init_or_handshake_state(or_connection_t *conn, int started_here)
|
||||
{
|
||||
or_handshake_state_t *s;
|
||||
s = conn->handshake_state = tor_malloc_zero(sizeof(or_handshake_state_t));
|
||||
s->started_here = started_here ? 1 : 0;
|
||||
if (tor_tls_get_random_values(conn->tls,
|
||||
conn->handshake_state->client_random,
|
||||
conn->handshake_state->server_random) < 0)
|
||||
return -1;
|
||||
if (started_here) {
|
||||
if (tor_tls_get_cert_digests(conn->tls,
|
||||
s->client_cert_digest,
|
||||
s->server_cert_digest)<0)
|
||||
return -1;
|
||||
} else {
|
||||
if (tor_tls_get_cert_digests(conn->tls,
|
||||
s->server_cert_digest,
|
||||
s->client_cert_digest)<0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
void
|
||||
|
@ -868,8 +868,10 @@ typedef struct or_handshake_state_t {
|
||||
unsigned int authenticated : 1;
|
||||
|
||||
/* from tls */
|
||||
char client_random[32];
|
||||
char server_random[32];
|
||||
char client_random[TOR_TLS_RANDOM_LEN];
|
||||
char server_random[TOR_TLS_RANDOM_LEN];
|
||||
char client_cert_digest[DIGEST_LEN]; /* may also be set by netinfo */
|
||||
char server_cert_digest[DIGEST_LEN];
|
||||
|
||||
/* from netinfo */
|
||||
long apparent_skew;
|
||||
|
Loading…
Reference in New Issue
Block a user