Loading src/or/command.c +278 −0 Original line number Diff line number Diff line Loading @@ -660,3 +660,281 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) assert_connection_ok(TO_CONN(conn),time(NULL)); } /** Process a CERT cell from an OR connection. * * If the other side should not have sent us a CERT cell, or the cell is * malformed, or it is supposed to authenticate the TLS key but it doesn't, * then mark the connection. * * If the cell has a good cert chain and we're doing a v3 handshake, then * store the certificates in or_handshake_state. If this is the client side * of the connection, we then authenticate the server or mark the connection. * If it's the server side, wait for an AUTHENTICATE cell. */ static void command_process_cert_cell(var_cell_t *cell, or_connection_t *conn) { #define ERR(s) \ do { \ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ "Received a bad CERT cell from %s:%d: %s", \ conn->_base.address, conn->_base.port, (s)); \ connection_mark_for_close(TO_CONN(conn)); \ goto err; \ } while (0) tor_cert_t *link_cert = NULL; tor_cert_t *id_cert = NULL; tor_cert_t *auth_cert = NULL; uint8_t *ptr; int n_certs, i; if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) ERR("We're not doing a v3 handshake!"); if (conn->handshake_state->received_cert_cell) ERR("We already got one"); if (cell->payload_len < 1) ERR("It had no body"); if (cell->circ_id) ERR("It had a nonzero circuit ID"); n_certs = cell->payload[0]; ptr = cell->payload + 1; for (i = 0; i < n_certs; ++i) { uint8_t cert_type; uint16_t cert_len; if (ptr + 3 > cell->payload + cell->payload_len) { goto truncated; } cert_type = *ptr; cert_len = ntohs(get_uint16(ptr+1)); if (ptr + 3 + cert_len > cell->payload + cell->payload_len) { goto truncated; } if (cert_type == OR_CERT_TYPE_TLS_LINK || cert_type == OR_CERT_TYPE_ID_1024 || cert_type == OR_CERT_TYPE_AUTH_1024) { tor_cert_t *cert = tor_cert_decode(ptr + 3, cert_len); if (!cert) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Received undecodable certificate in CERT cell from %s:%d", conn->_base.address, conn->_base.port); } else { if (cert_type == OR_CERT_TYPE_TLS_LINK && !link_cert) link_cert = cert; else if (cert_type == OR_CERT_TYPE_ID_1024 && !id_cert) id_cert = cert; else if (cert_type == OR_CERT_TYPE_AUTH_1024 && !auth_cert) auth_cert = cert; else tor_cert_free(cert); } } ptr += 3 + cert_len; continue; truncated: ERR("It ends in the middle of a certificate"); } if (conn->handshake_state->started_here) { 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(conn->tls, link_cert)) { ERR("The link certificate didn't match the TLS public key"); } if (! tor_tls_cert_is_valid(link_cert, id_cert)) ERR("The link certificate was not valid"); if (! tor_tls_cert_is_valid(id_cert, id_cert)) ERR("The ID certificate was not valid"); /* XXXX okay, we just got authentication. Do something about that. */ conn->handshake_state->id_cert = id_cert; id_cert = NULL; } else { if (! (id_cert && auth_cert)) ERR("The certs we wanted were missing"); /* Remember these certificates so we can check an AUTHENTICATE cell */ conn->handshake_state->id_cert = id_cert; conn->handshake_state->auth_cert = auth_cert; if (! tor_tls_cert_is_valid(auth_cert, id_cert)) ERR("The authentication certificate was not valid"); if (! tor_tls_cert_is_valid(id_cert, id_cert)) ERR("The ID certificate was not valid"); /* XXXX check more stuff? */ id_cert = auth_cert = NULL; } conn->handshake_state->received_cert_cell = 1; err: tor_cert_free(id_cert); tor_cert_free(link_cert); tor_cert_free(auth_cert); #undef ERR } /** Process an AUTH_CHALLENGE cell from an OR connection. * * If we weren't supposed to get one (for example, because we're not the * originator of the connection), or it's ill-formed, or we aren't doing a v3 * handshake, mark the connection. If the cell is well-formed but we don't * want to authenticate, just drop it. If the cell is well-formed *and* we * want to authenticate, send an AUTHENTICATE cell. */ static void command_process_auth_challenge_cell(var_cell_t *cell, or_connection_t *conn) { int n_types, i, use_type = -1; uint8_t *cp; #define ERR(s) \ do { \ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ "Received a bad AUTH_CHALLENGE cell from %s:%d: %s", \ conn->_base.address, conn->_base.port, (s)); \ connection_mark_for_close(TO_CONN(conn)); \ return; \ } while (0) if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) ERR("We're not currently doing a v3 handshake"); if (! conn->handshake_state->started_here) ERR("We didn't originate this connection"); if (conn->handshake_state->received_auth_challenge) ERR("We already received one"); if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2) ERR("It was too short"); if (cell->circ_id) ERR("It had a nonzero circuit ID"); n_types = ntohs(get_uint16(cell->payload + OR_AUTH_CHALLENGE_LEN)); if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2 + 2*n_types) ERR("It looks truncated"); memcpy(conn->handshake_state->auth_challenge, cell->payload, OR_AUTH_CHALLENGE_LEN); /* Now see if there is an authentication type we can use */ cp=cell->payload+OR_AUTH_CHALLENGE_LEN+2; for (i=0; i < n_types; ++i, cp += 2) { uint16_t authtype = ntohs(get_uint16(cp)); if (authtype == AUTHTYPE_RSA_SHA256_TLSSECRET) use_type = authtype; } conn->handshake_state->received_auth_challenge = 1; /* Send back authentication if we want, and if use_type is set */ #undef ERR } /** Process an AUTHENTICATE cell from an OR connection. * * If it's ill-formed or we weren't supposed to get one or we're not doing a * v3 handshake, then mark the connection. If it does not authenticate the * other side of the connection successfully (because it isn't signed right, * we didn't get a CERT cell, etc) mark the connection. Otherwise, accept * the identity of the router on the other side of the connection. */ static void command_process_authenticate_cell(or_connection_t *conn, var_cell_t *cell) { uint8_t expected[V3_AUTH_FIXED_PART_LEN]; const uint8_t *auth; int authlen; #define ERR(s) \ do { \ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ "Received a bad AUTHETNICATE cell from %s:%d: %s", \ conn->_base.address, conn->_base.port, (s)); \ connection_mark_for_close(TO_CONN(conn)); \ return; \ } while (0) if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) ERR("We're not doing a v3 handshake"); if (! conn->handshake_state->started_here) ERR("We originated this connection"); if (conn->handshake_state->received_authenticate) ERR("We already got one!"); if (conn->handshake_state->auth_cert == NULL) ERR("We never got an authentication certificate"); if (cell->payload_len < 4) ERR("Cell was way too short"); auth = cell->payload; { uint16_t type = ntohs(get_uint16(auth)); uint16_t len = ntohs(get_uint16(auth+2)); if (4 + len > cell->payload_len) ERR("Authenticator was truncated"); if (type != AUTHTYPE_RSA_SHA256_TLSSECRET) ERR("Authenticator type was not recognized"); auth += 4; authlen = len; } if (authlen < V3_AUTH_BODY_LEN + 1) ERR("Authenticator was too short"); if (connection_or_compute_authenticate_cell_body( conn, expected, sizeof(expected), NULL, 1) < 0) ERR("Couldn't compute expected AUTHENTICATE cell body"); if (tor_memneq(expected, auth, sizeof(expected))) ERR("Some field in the AUTHENTICATE cell body was not as expected"); { crypto_pk_env_t *pk = tor_tls_cert_get_key( conn->handshake_state->auth_cert); char d[DIGEST256_LEN]; char *signed_data; size_t keysize; int signed_len; crypto_digest256(d, (char*)auth, V3_AUTH_BODY_LEN, DIGEST_SHA256); keysize = crypto_pk_keysize(pk); signed_data = tor_malloc(keysize); signed_len = crypto_pk_public_checksig(pk, signed_data, keysize, (char*)auth + V3_AUTH_BODY_LEN, authlen - V3_AUTH_BODY_LEN); if (signed_len < 0) { tor_free(signed_data); ERR("Signature wasn't valid"); } if (signed_len < DIGEST256_LEN) { tor_free(signed_data); ERR("Not enough data was signed"); } if (tor_memneq(signed_data, d, DIGEST256_LEN)) { tor_free(signed_data); ERR("Signature did not match data to be signed."); } tor_free(signed_data); } /* XXXX we're authenticated. Now remember the fact, and remember whom we're authenticated to. */ conn->handshake_state->received_authenticate = 1; #undef ERR } void dummy_function(void); void dummy_function(void) { /* this is only here to avoid 'static function isn't used' warnings */ command_process_auth_challenge_cell(NULL, NULL); command_process_cert_cell(NULL, NULL); command_process_authenticate_cell(NULL, NULL); } src/or/connection_or.c +7 −17 Original line number Diff line number Diff line Loading @@ -1761,10 +1761,6 @@ connection_or_send_netinfo(or_connection_t *conn) return 0; } /** DOCDOC */ #define OR_CERT_TYPE_TLS_LINK 1 #define OR_CERT_TYPE_ID_1024 2 /** Send a CERT cell on the connection <b>conn</b>. Return 0 on success, -1 * on failure. */ int Loading Loading @@ -1846,23 +1842,17 @@ connection_or_send_auth_challenge_cell(or_connection_t *conn) return 0; } /** DOCDOC */ #define V3_HS_AUTH_FIXED_PART_LEN (8+(32*6)) #define V3_HS_AUTH_BODY_LEN (V3_HS_AUTH_FIXED_PART_LEN + 8 + 16) #define AUTHTYPE_RSA_SHA256_TLSSECRET 1 /** Compute the main body of an AUTHENTICATE cell that a client can use * to authenticate itself on a v3 handshake for <b>conn</b>. Write it to the * <b>outlen</b>-byte buffer at <b>out</b>. * * If <b>server</b> is true, only calculate the first * V3_HS_AUTH_FIXED_PART_LEN bytes -- the part of the authenticator that's * V3_AUTH_FIXED_PART_LEN bytes -- the part of the authenticator that's * determined by the rest of the handshake, and which match the provided value * exactly. * * If <b>server</b> is false and <b>signing_key</b> is NULL, calculate the * first V3_HS_AUTH_BODY_LEN bytes of the authenticator (that is, everything * first V3_AUTH_BODY_LEN bytes of the authenticator (that is, everything * that should be signed), but don't actually sign it. * * If <b>server</b> is false and <b>signing_key</b> is provided, calculate the Loading @@ -1878,8 +1868,8 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn, /* assert state is reasonable XXXX */ if (outlen < V3_HS_AUTH_FIXED_PART_LEN || (!server && outlen < V3_HS_AUTH_BODY_LEN)) if (outlen < V3_AUTH_FIXED_PART_LEN || (!server && outlen < V3_AUTH_BODY_LEN)) return -1; ptr = out; Loading Loading @@ -1950,7 +1940,7 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn, tor_tls_get_tlssecrets(conn->tls, ptr); ptr += 32; tor_assert(ptr - out == V3_HS_AUTH_FIXED_PART_LEN); tor_assert(ptr - out == V3_AUTH_FIXED_PART_LEN); if (server) return ptr-out; Loading @@ -1969,7 +1959,7 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn, crypto_rand((char*)ptr, 16); ptr += 16; tor_assert(ptr - out == V3_HS_AUTH_BODY_LEN); tor_assert(ptr - out == V3_AUTH_BODY_LEN); if (!signing_key) return ptr - out; Loading Loading @@ -2004,7 +1994,7 @@ connection_or_send_authenticate_cell(or_connection_t *conn) if (!pk) return -1;/*XXXX log*/ cell_maxlen = 4 + /* overhead */ V3_HS_AUTH_BODY_LEN + /* Authentication body */ V3_AUTH_BODY_LEN + /* Authentication body */ crypto_pk_keysize(pk) + /* Max signature length */ 16 /* just in case XXXX */ ; Loading src/or/or.h +53 −0 Original line number Diff line number Diff line Loading @@ -1087,6 +1087,43 @@ typedef struct listener_connection_t { /** Minimum length of the random part of an AUTH_CHALLENGE cell. */ #define OR_AUTH_CHALLENGE_LEN 32 /** * @name Certificate types for CERT cells. * * These values are defined by the protocol, and affect how an X509 * certificate in a CERT cell is interpreted and used. * * @{ */ /** A certificate that authenticates a TLS link key. The subject key * must match the key used in the TLS handshake; it must be signed by * the identity key. */ #define OR_CERT_TYPE_TLS_LINK 1 /** A self-signed identity certificate. The subject key must be a * 1024-bit RSA key. */ #define OR_CERT_TYPE_ID_1024 2 /** A certificate that authenticates a key used in an AUTHENTICATE cell * in the v3 handshake. The subject key must be a 1024-bit RSA key; it * must be signed by the identity key */ #define OR_CERT_TYPE_AUTH_1024 3 /**@}*/ /** The one currently supported type of AUTHENTICATE cell. It contains * a bunch of structures signed with an RSA1024 key. The signed * structures include a HMAC using negotiated TLS secrets, and a digest * of all cells sent or received before the AUTHENTICATE cell (including * the random server-generated AUTH_CHALLENGE cell). */ #define AUTHTYPE_RSA_SHA256_TLSSECRET 1 /** The length of the part of the AUTHENTICATE cell body that the client and * server can generate independently (when using RSA_SHA256_TLSSECRET). It * contains everything except the client's timestamp, the client's randomly * generated nonce, and the signature. */ #define V3_AUTH_FIXED_PART_LEN (8+(32*6)) /** The length of the part of the AUTHENTICATE cell body that the client * signs. */ #define V3_AUTH_BODY_LEN (V3_AUTH_FIXED_PART_LEN + 8 + 16) /** Stores flags and information related to the portion of a v2/v3 Tor OR * connection handshake that happens after the TLS handshake is finished. */ Loading @@ -1098,6 +1135,12 @@ typedef struct or_handshake_state_t { unsigned int started_here : 1; /** True iff we have received and processed a VERSIONS cell. */ unsigned int received_versions : 1; /** True iff we have received and processed an AUTH_CHALLENGE cell */ unsigned int received_auth_challenge : 1; /** True iff we have received and processed a CERT cell. */ unsigned int received_cert_cell : 1; /** True iff we have received and processed an AUTHENTICATE cell */ unsigned int received_authenticate : 1; /** Digests of the cells that we have sent or received as part of a V3 * handshake. Used for making and checking AUTHENTICATE cells. Loading @@ -1108,6 +1151,16 @@ typedef struct or_handshake_state_t { crypto_digest_env_t *digest_received; /** @} */ /** Certificates that a connection initiator sent us in a CERT 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_cert_t *auth_cert; /** A self-signed identity certificate */ tor_cert_t *id_cert; /**@}*/ } or_handshake_state_t; /** Subtype of connection_t for an "OR connection" -- that is, one that speaks Loading Loading
src/or/command.c +278 −0 Original line number Diff line number Diff line Loading @@ -660,3 +660,281 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) assert_connection_ok(TO_CONN(conn),time(NULL)); } /** Process a CERT cell from an OR connection. * * If the other side should not have sent us a CERT cell, or the cell is * malformed, or it is supposed to authenticate the TLS key but it doesn't, * then mark the connection. * * If the cell has a good cert chain and we're doing a v3 handshake, then * store the certificates in or_handshake_state. If this is the client side * of the connection, we then authenticate the server or mark the connection. * If it's the server side, wait for an AUTHENTICATE cell. */ static void command_process_cert_cell(var_cell_t *cell, or_connection_t *conn) { #define ERR(s) \ do { \ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ "Received a bad CERT cell from %s:%d: %s", \ conn->_base.address, conn->_base.port, (s)); \ connection_mark_for_close(TO_CONN(conn)); \ goto err; \ } while (0) tor_cert_t *link_cert = NULL; tor_cert_t *id_cert = NULL; tor_cert_t *auth_cert = NULL; uint8_t *ptr; int n_certs, i; if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) ERR("We're not doing a v3 handshake!"); if (conn->handshake_state->received_cert_cell) ERR("We already got one"); if (cell->payload_len < 1) ERR("It had no body"); if (cell->circ_id) ERR("It had a nonzero circuit ID"); n_certs = cell->payload[0]; ptr = cell->payload + 1; for (i = 0; i < n_certs; ++i) { uint8_t cert_type; uint16_t cert_len; if (ptr + 3 > cell->payload + cell->payload_len) { goto truncated; } cert_type = *ptr; cert_len = ntohs(get_uint16(ptr+1)); if (ptr + 3 + cert_len > cell->payload + cell->payload_len) { goto truncated; } if (cert_type == OR_CERT_TYPE_TLS_LINK || cert_type == OR_CERT_TYPE_ID_1024 || cert_type == OR_CERT_TYPE_AUTH_1024) { tor_cert_t *cert = tor_cert_decode(ptr + 3, cert_len); if (!cert) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Received undecodable certificate in CERT cell from %s:%d", conn->_base.address, conn->_base.port); } else { if (cert_type == OR_CERT_TYPE_TLS_LINK && !link_cert) link_cert = cert; else if (cert_type == OR_CERT_TYPE_ID_1024 && !id_cert) id_cert = cert; else if (cert_type == OR_CERT_TYPE_AUTH_1024 && !auth_cert) auth_cert = cert; else tor_cert_free(cert); } } ptr += 3 + cert_len; continue; truncated: ERR("It ends in the middle of a certificate"); } if (conn->handshake_state->started_here) { 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(conn->tls, link_cert)) { ERR("The link certificate didn't match the TLS public key"); } if (! tor_tls_cert_is_valid(link_cert, id_cert)) ERR("The link certificate was not valid"); if (! tor_tls_cert_is_valid(id_cert, id_cert)) ERR("The ID certificate was not valid"); /* XXXX okay, we just got authentication. Do something about that. */ conn->handshake_state->id_cert = id_cert; id_cert = NULL; } else { if (! (id_cert && auth_cert)) ERR("The certs we wanted were missing"); /* Remember these certificates so we can check an AUTHENTICATE cell */ conn->handshake_state->id_cert = id_cert; conn->handshake_state->auth_cert = auth_cert; if (! tor_tls_cert_is_valid(auth_cert, id_cert)) ERR("The authentication certificate was not valid"); if (! tor_tls_cert_is_valid(id_cert, id_cert)) ERR("The ID certificate was not valid"); /* XXXX check more stuff? */ id_cert = auth_cert = NULL; } conn->handshake_state->received_cert_cell = 1; err: tor_cert_free(id_cert); tor_cert_free(link_cert); tor_cert_free(auth_cert); #undef ERR } /** Process an AUTH_CHALLENGE cell from an OR connection. * * If we weren't supposed to get one (for example, because we're not the * originator of the connection), or it's ill-formed, or we aren't doing a v3 * handshake, mark the connection. If the cell is well-formed but we don't * want to authenticate, just drop it. If the cell is well-formed *and* we * want to authenticate, send an AUTHENTICATE cell. */ static void command_process_auth_challenge_cell(var_cell_t *cell, or_connection_t *conn) { int n_types, i, use_type = -1; uint8_t *cp; #define ERR(s) \ do { \ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ "Received a bad AUTH_CHALLENGE cell from %s:%d: %s", \ conn->_base.address, conn->_base.port, (s)); \ connection_mark_for_close(TO_CONN(conn)); \ return; \ } while (0) if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) ERR("We're not currently doing a v3 handshake"); if (! conn->handshake_state->started_here) ERR("We didn't originate this connection"); if (conn->handshake_state->received_auth_challenge) ERR("We already received one"); if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2) ERR("It was too short"); if (cell->circ_id) ERR("It had a nonzero circuit ID"); n_types = ntohs(get_uint16(cell->payload + OR_AUTH_CHALLENGE_LEN)); if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2 + 2*n_types) ERR("It looks truncated"); memcpy(conn->handshake_state->auth_challenge, cell->payload, OR_AUTH_CHALLENGE_LEN); /* Now see if there is an authentication type we can use */ cp=cell->payload+OR_AUTH_CHALLENGE_LEN+2; for (i=0; i < n_types; ++i, cp += 2) { uint16_t authtype = ntohs(get_uint16(cp)); if (authtype == AUTHTYPE_RSA_SHA256_TLSSECRET) use_type = authtype; } conn->handshake_state->received_auth_challenge = 1; /* Send back authentication if we want, and if use_type is set */ #undef ERR } /** Process an AUTHENTICATE cell from an OR connection. * * If it's ill-formed or we weren't supposed to get one or we're not doing a * v3 handshake, then mark the connection. If it does not authenticate the * other side of the connection successfully (because it isn't signed right, * we didn't get a CERT cell, etc) mark the connection. Otherwise, accept * the identity of the router on the other side of the connection. */ static void command_process_authenticate_cell(or_connection_t *conn, var_cell_t *cell) { uint8_t expected[V3_AUTH_FIXED_PART_LEN]; const uint8_t *auth; int authlen; #define ERR(s) \ do { \ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ "Received a bad AUTHETNICATE cell from %s:%d: %s", \ conn->_base.address, conn->_base.port, (s)); \ connection_mark_for_close(TO_CONN(conn)); \ return; \ } while (0) if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) ERR("We're not doing a v3 handshake"); if (! conn->handshake_state->started_here) ERR("We originated this connection"); if (conn->handshake_state->received_authenticate) ERR("We already got one!"); if (conn->handshake_state->auth_cert == NULL) ERR("We never got an authentication certificate"); if (cell->payload_len < 4) ERR("Cell was way too short"); auth = cell->payload; { uint16_t type = ntohs(get_uint16(auth)); uint16_t len = ntohs(get_uint16(auth+2)); if (4 + len > cell->payload_len) ERR("Authenticator was truncated"); if (type != AUTHTYPE_RSA_SHA256_TLSSECRET) ERR("Authenticator type was not recognized"); auth += 4; authlen = len; } if (authlen < V3_AUTH_BODY_LEN + 1) ERR("Authenticator was too short"); if (connection_or_compute_authenticate_cell_body( conn, expected, sizeof(expected), NULL, 1) < 0) ERR("Couldn't compute expected AUTHENTICATE cell body"); if (tor_memneq(expected, auth, sizeof(expected))) ERR("Some field in the AUTHENTICATE cell body was not as expected"); { crypto_pk_env_t *pk = tor_tls_cert_get_key( conn->handshake_state->auth_cert); char d[DIGEST256_LEN]; char *signed_data; size_t keysize; int signed_len; crypto_digest256(d, (char*)auth, V3_AUTH_BODY_LEN, DIGEST_SHA256); keysize = crypto_pk_keysize(pk); signed_data = tor_malloc(keysize); signed_len = crypto_pk_public_checksig(pk, signed_data, keysize, (char*)auth + V3_AUTH_BODY_LEN, authlen - V3_AUTH_BODY_LEN); if (signed_len < 0) { tor_free(signed_data); ERR("Signature wasn't valid"); } if (signed_len < DIGEST256_LEN) { tor_free(signed_data); ERR("Not enough data was signed"); } if (tor_memneq(signed_data, d, DIGEST256_LEN)) { tor_free(signed_data); ERR("Signature did not match data to be signed."); } tor_free(signed_data); } /* XXXX we're authenticated. Now remember the fact, and remember whom we're authenticated to. */ conn->handshake_state->received_authenticate = 1; #undef ERR } void dummy_function(void); void dummy_function(void) { /* this is only here to avoid 'static function isn't used' warnings */ command_process_auth_challenge_cell(NULL, NULL); command_process_cert_cell(NULL, NULL); command_process_authenticate_cell(NULL, NULL); }
src/or/connection_or.c +7 −17 Original line number Diff line number Diff line Loading @@ -1761,10 +1761,6 @@ connection_or_send_netinfo(or_connection_t *conn) return 0; } /** DOCDOC */ #define OR_CERT_TYPE_TLS_LINK 1 #define OR_CERT_TYPE_ID_1024 2 /** Send a CERT cell on the connection <b>conn</b>. Return 0 on success, -1 * on failure. */ int Loading Loading @@ -1846,23 +1842,17 @@ connection_or_send_auth_challenge_cell(or_connection_t *conn) return 0; } /** DOCDOC */ #define V3_HS_AUTH_FIXED_PART_LEN (8+(32*6)) #define V3_HS_AUTH_BODY_LEN (V3_HS_AUTH_FIXED_PART_LEN + 8 + 16) #define AUTHTYPE_RSA_SHA256_TLSSECRET 1 /** Compute the main body of an AUTHENTICATE cell that a client can use * to authenticate itself on a v3 handshake for <b>conn</b>. Write it to the * <b>outlen</b>-byte buffer at <b>out</b>. * * If <b>server</b> is true, only calculate the first * V3_HS_AUTH_FIXED_PART_LEN bytes -- the part of the authenticator that's * V3_AUTH_FIXED_PART_LEN bytes -- the part of the authenticator that's * determined by the rest of the handshake, and which match the provided value * exactly. * * If <b>server</b> is false and <b>signing_key</b> is NULL, calculate the * first V3_HS_AUTH_BODY_LEN bytes of the authenticator (that is, everything * first V3_AUTH_BODY_LEN bytes of the authenticator (that is, everything * that should be signed), but don't actually sign it. * * If <b>server</b> is false and <b>signing_key</b> is provided, calculate the Loading @@ -1878,8 +1868,8 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn, /* assert state is reasonable XXXX */ if (outlen < V3_HS_AUTH_FIXED_PART_LEN || (!server && outlen < V3_HS_AUTH_BODY_LEN)) if (outlen < V3_AUTH_FIXED_PART_LEN || (!server && outlen < V3_AUTH_BODY_LEN)) return -1; ptr = out; Loading Loading @@ -1950,7 +1940,7 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn, tor_tls_get_tlssecrets(conn->tls, ptr); ptr += 32; tor_assert(ptr - out == V3_HS_AUTH_FIXED_PART_LEN); tor_assert(ptr - out == V3_AUTH_FIXED_PART_LEN); if (server) return ptr-out; Loading @@ -1969,7 +1959,7 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn, crypto_rand((char*)ptr, 16); ptr += 16; tor_assert(ptr - out == V3_HS_AUTH_BODY_LEN); tor_assert(ptr - out == V3_AUTH_BODY_LEN); if (!signing_key) return ptr - out; Loading Loading @@ -2004,7 +1994,7 @@ connection_or_send_authenticate_cell(or_connection_t *conn) if (!pk) return -1;/*XXXX log*/ cell_maxlen = 4 + /* overhead */ V3_HS_AUTH_BODY_LEN + /* Authentication body */ V3_AUTH_BODY_LEN + /* Authentication body */ crypto_pk_keysize(pk) + /* Max signature length */ 16 /* just in case XXXX */ ; Loading
src/or/or.h +53 −0 Original line number Diff line number Diff line Loading @@ -1087,6 +1087,43 @@ typedef struct listener_connection_t { /** Minimum length of the random part of an AUTH_CHALLENGE cell. */ #define OR_AUTH_CHALLENGE_LEN 32 /** * @name Certificate types for CERT cells. * * These values are defined by the protocol, and affect how an X509 * certificate in a CERT cell is interpreted and used. * * @{ */ /** A certificate that authenticates a TLS link key. The subject key * must match the key used in the TLS handshake; it must be signed by * the identity key. */ #define OR_CERT_TYPE_TLS_LINK 1 /** A self-signed identity certificate. The subject key must be a * 1024-bit RSA key. */ #define OR_CERT_TYPE_ID_1024 2 /** A certificate that authenticates a key used in an AUTHENTICATE cell * in the v3 handshake. The subject key must be a 1024-bit RSA key; it * must be signed by the identity key */ #define OR_CERT_TYPE_AUTH_1024 3 /**@}*/ /** The one currently supported type of AUTHENTICATE cell. It contains * a bunch of structures signed with an RSA1024 key. The signed * structures include a HMAC using negotiated TLS secrets, and a digest * of all cells sent or received before the AUTHENTICATE cell (including * the random server-generated AUTH_CHALLENGE cell). */ #define AUTHTYPE_RSA_SHA256_TLSSECRET 1 /** The length of the part of the AUTHENTICATE cell body that the client and * server can generate independently (when using RSA_SHA256_TLSSECRET). It * contains everything except the client's timestamp, the client's randomly * generated nonce, and the signature. */ #define V3_AUTH_FIXED_PART_LEN (8+(32*6)) /** The length of the part of the AUTHENTICATE cell body that the client * signs. */ #define V3_AUTH_BODY_LEN (V3_AUTH_FIXED_PART_LEN + 8 + 16) /** Stores flags and information related to the portion of a v2/v3 Tor OR * connection handshake that happens after the TLS handshake is finished. */ Loading @@ -1098,6 +1135,12 @@ typedef struct or_handshake_state_t { unsigned int started_here : 1; /** True iff we have received and processed a VERSIONS cell. */ unsigned int received_versions : 1; /** True iff we have received and processed an AUTH_CHALLENGE cell */ unsigned int received_auth_challenge : 1; /** True iff we have received and processed a CERT cell. */ unsigned int received_cert_cell : 1; /** True iff we have received and processed an AUTHENTICATE cell */ unsigned int received_authenticate : 1; /** Digests of the cells that we have sent or received as part of a V3 * handshake. Used for making and checking AUTHENTICATE cells. Loading @@ -1108,6 +1151,16 @@ typedef struct or_handshake_state_t { crypto_digest_env_t *digest_received; /** @} */ /** Certificates that a connection initiator sent us in a CERT 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_cert_t *auth_cert; /** A self-signed identity certificate */ tor_cert_t *id_cert; /**@}*/ } or_handshake_state_t; /** Subtype of connection_t for an "OR connection" -- that is, one that speaks Loading