diff --git a/src/common/tortls.c b/src/common/tortls.c index 23889be259..eaa5748f33 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -2448,6 +2448,28 @@ tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out)) return 0; } +/** Using the RFC5705 key material exporting construction, and the + * provided context (context_len bytes long) and + * label (a NUL-terminated string), compute a 32-byte secret in + * secrets_out that only the parties to this TLS session can + * compute. Return 0 on success and -1 on failure. + */ +MOCK_IMPL(int, +tor_tls_export_key_material,(tor_tls_t *tls, uint8_t *secrets_out, + const uint8_t *context, + size_t context_len, + const char *label)) +{ + tor_assert(tls); + tor_assert(tls->ssl); + + int r = SSL_export_keying_material(tls->ssl, + secrets_out, DIGEST256_LEN, + label, strlen(label), + context, context_len, 1); + return (r == 1) ? 0 : -1; +} + /** Examine the amount of memory used and available for buffers in tls. * Set *rbuf_capacity to the amount of storage allocated for the read * buffer and *rbuf_bytes to the amount actually used. diff --git a/src/common/tortls.h b/src/common/tortls.h index 7c035a2cd5..fe5898ef5c 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -226,6 +226,11 @@ int tor_tls_used_v1_handshake(tor_tls_t *tls); int tor_tls_get_num_server_handshakes(tor_tls_t *tls); int tor_tls_server_got_renegotiate(tor_tls_t *tls); MOCK_DECL(int,tor_tls_get_tlssecrets,(tor_tls_t *tls, uint8_t *secrets_out)); +MOCK_DECL(int,tor_tls_export_key_material,( + tor_tls_t *tls, uint8_t *secrets_out, + const uint8_t *context, + size_t context_len, + const char *label)); /* Log and abort if there are unhandled TLS errors in OpenSSL's error stack. */ diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 09579f80e1..d06a246ee2 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -2318,15 +2318,34 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn, auth1_t *auth = NULL; auth_ctx_t *ctx = auth_ctx_new(); int result; + int old_tlssecrets_algorithm = 0; + const char *authtype_str = NULL; + + int is_ed = 0; + const int authtype = 1; /* XXXX this should be an argument. */ /* assert state is reasonable XXXX */ - - ctx->is_ed = 0; + switch (authtype) { + case AUTHTYPE_RSA_SHA256_TLSSECRET: + authtype_str = "AUTH0001"; + old_tlssecrets_algorithm = 1; + break; + case AUTHTYPE_RSA_SHA256_RFC5705: + authtype_str = "AUTH0002"; + break; + case AUTHTYPE_ED25519_SHA256_RFC5705: + authtype_str = "AUTH0003"; + is_ed = 1; + break; + default: + tor_assert(0); + break; + } auth = auth1_new(); /* Type: 8 bytes. */ - memcpy(auth1_getarray_type(auth), "AUTH0001", 8); + memcpy(auth1_getarray_type(auth), authtype_str, 8); { const tor_x509_cert_t *id_cert=NULL, *link_cert=NULL; @@ -2380,7 +2399,8 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn, cert = freecert; } if (!cert) { - log_warn(LD_OR, "Unable to find cert when making AUTH1 data."); + log_warn(LD_OR, "Unable to find cert when making %s data.", + authtype_str); goto err; } @@ -2392,7 +2412,16 @@ connection_or_compute_authenticate_cell_body(or_connection_t *conn, } /* HMAC of clientrandom and serverrandom using master key : 32 octets */ - tor_tls_get_tlssecrets(conn->tls, auth->tlssecrets); + if (old_tlssecrets_algorithm) { + tor_tls_get_tlssecrets(conn->tls, auth->tlssecrets); + } else { + char label[128]; + tor_snprintf(label, sizeof(label), + "EXPORTER FOR TOR TLS CLIENT BINDING %s", authtype_str); + tor_tls_export_key_material(conn->tls, auth->tlssecrets, + auth->cid, sizeof(auth->cid), + label); + } /* 8 octets were reserved for the current time, but we're trying to get out * of the habit of sending time around willynilly. Fortunately, nothing diff --git a/src/or/or.h b/src/or/or.h index 5b9b007ac1..402fbfde6b 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1348,13 +1348,34 @@ typedef struct listener_connection_t { #define OR_CERT_TYPE_RSA_ED_CROSSCERT 7 /**@}*/ -/** The one currently supported type of AUTHENTICATE cell. It contains +/** The first 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 +/** As AUTHTYPE_RSA_SHA256_TLSSECRET, but instead of using the + * negotiated TLS secrets, uses exported keying material from the TLS + * session as described in RFC 5705. + * + * Not used by today's tors, since everything that supports this + * also supports ED25519_SHA3_5705, which is better. + **/ +#define AUTHTYPE_RSA_SHA256_RFC5705 2 +/** As AUTHTYPE_RSA_SHA256_RFC5705, but uses an Ed25519 identity key to + * authenticate. */ +#define AUTHTYPE_ED25519_SHA256_RFC5705 3 +/* + * NOTE: authchallenge_type_is_better() relies on these AUTHTYPE codes + * being sorted in order of preference. If we someday add one with + * a higher numerical value that we don't like as much, we should revise + * authchallenge_type_is_better(). + */ + + + + /** The length of the part of the AUTHENTICATE cell body that the client and * server can generate independently (when using RSA_SHA256_TLSSECRET). It