Skip to content

Commit

Permalink
Add the SSL_OP_NO_RENEGOTIATION option to 1.1.0
Browse files Browse the repository at this point in the history
This is based on a heavily modified version of commit db0f35d by Todd
Short from the master branch.

We are adding this because it used to be possible to disable reneg using
the flag SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS in 1.0.2. This is no longer
possible because of the opacity work.

A point to note about this is that if an application built against new
1.1.0 headers (that know about the new option SSL_OP_NO_RENEGOTIATION
option) is run using an older version of 1.1.0 (that doesn't know about
the option) then the option will be accepted but nothing will happen, i.e.
renegotiation will not be prevented. There's probably not much we can do
about that.

Fixes #4739

Reviewed-by: Ben Kaduk <kaduk@mit.edu>
(Merged from #4901)
  • Loading branch information
mattcaswell committed Jan 30, 2018
1 parent 1249258 commit 6e127fd
Show file tree
Hide file tree
Showing 15 changed files with 262 additions and 19 deletions.
5 changes: 4 additions & 1 deletion apps/apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
OPT_S_ONRESUMP, OPT_S_NOLEGACYCONN, OPT_S_STRICT, OPT_S_SIGALGS, \
OPT_S_CLIENTSIGALGS, OPT_S_CURVES, OPT_S_NAMEDCURVE, OPT_S_CIPHER, \
OPT_S_DEBUGBROKE, OPT_S_COMP, \
OPT_S__LAST
OPT_S_NO_RENEGOTIATION, OPT_S__LAST

# define OPT_S_OPTIONS \
{"no_ssl3", OPT_S_NOSSL3, '-',"Just disable SSLv3" }, \
Expand All @@ -230,6 +230,8 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
{"serverpref", OPT_S_SERVERPREF, '-', "Use server's cipher preferences"}, \
{"legacy_renegotiation", OPT_S_LEGACYRENEG, '-', \
"Enable use of legacy renegotiation (dangerous)"}, \
{"no_renegotiation", OPT_S_NO_RENEGOTIATION, '-', \
"Disable all renegotiation."}, \
{"legacy_server_connect", OPT_S_LEGACYCONN, '-', \
"Allow initial connection to servers that don't support RI"}, \
{"no_resumption_on_reneg", OPT_S_ONRESUMP, '-', \
Expand Down Expand Up @@ -272,6 +274,7 @@ int set_cert_times(X509 *x, const char *startdate, const char *enddate,
case OPT_S_CURVES: \
case OPT_S_NAMEDCURVE: \
case OPT_S_CIPHER: \
case OPT_S_NO_RENEGOTIATION: \
case OPT_S_DEBUGBROKE

#define IS_NO_PROT_FLAG(o) \
Expand Down
3 changes: 3 additions & 0 deletions apps/s_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -2575,6 +2575,9 @@ static int init_ssl_connection(SSL *con)
BIO_printf(bio_s_out, "Reused session-id\n");
BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n",
SSL_get_secure_renegotiation_support(con) ? "" : " NOT");
if ((SSL_get_options(con) & SSL_OP_NO_RENEGOTIATION))
BIO_printf(bio_s_out, "Renegotiation is DISABLED\n");

if (keymatexportlabel != NULL) {
BIO_printf(bio_s_out, "Keying material exporter:\n");
BIO_printf(bio_s_out, " Label: '%s'\n", keymatexportlabel);
Expand Down
10 changes: 10 additions & 0 deletions doc/ssl/SSL_CONF_cmd.pod
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ Attempts to use the file B<value> as the set of temporary DH parameters for
the appropriate context. This option is only supported if certificate
operations are permitted.

=item B<-no_renegotiation>

Disables all attempts at renegotiation in TLSv1.2 and earlier, same as setting
B<SSL_OP_NO_RENEGOTIATION>.

=item B<-min_protocol>, B<-max_protocol>

Sets the minimum and maximum supported protocol.
Expand Down Expand Up @@ -227,6 +232,11 @@ Attempts to use the file B<value> as the set of temporary DH parameters for
the appropriate context. This option is only supported if certificate
operations are permitted.

=item B<NoRenegotiation>

Disables all attempts at renegotiation in TLSv1.2 and earlier, same as setting
B<SSL_OP_NO_RENEGOTIATION>.

=item B<SignatureAlgorithms>

This sets the supported signature algorithms for TLS v1.2. For clients this
Expand Down
7 changes: 7 additions & 0 deletions doc/ssl/SSL_CTX_set_options.pod
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ RFC7366 Encrypt-then-MAC option on TLS and DTLS connection.
If this option is set, Encrypt-then-MAC is disabled. Clients will not
propose, and servers will not accept the extension.

=item SSL_OP_NO_RENEGOTIATION

Disable all renegotiation in TLSv1.2 and earlier. Do not send HelloRequest
messages, and ignore renegotiation requests via ClientHello.

=back

=head1 SECURE RENEGOTIATION
Expand Down Expand Up @@ -288,6 +293,8 @@ L<dhparam(1)>
The attempt to always try to use secure renegotiation was added in
Openssl 0.9.8m.

B<SSL_OP_NO_RENEGOTIATION> was added in OpenSSL 1.1.0h.

=head1 COPYRIGHT

Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
Expand Down
5 changes: 5 additions & 0 deletions include/openssl/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);
SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2)
# define SSL_OP_NO_DTLS_MASK (SSL_OP_NO_DTLSv1|SSL_OP_NO_DTLSv1_2)

/* Disallow all renegotiation */
# define SSL_OP_NO_RENEGOTIATION 0x40000000U

/*
* Make server add server-hello extension from early version of cryptopro
* draft, when GOST ciphersuite is negotiated. Required for interoperability
Expand Down Expand Up @@ -2201,6 +2204,8 @@ int ERR_load_SSL_strings(void);
# define SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT 311
# define SSL_F_SSL_PEEK 270
# define SSL_F_SSL_READ 223
# define SSL_F_SSL_RENEGOTIATE 516
# define SSL_F_SSL_RENEGOTIATE_ABBREVIATED 546
# define SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT 320
# define SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT 321
# define SSL_F_SSL_SESSION_DUP 348
Expand Down
10 changes: 8 additions & 2 deletions ssl/record/rec_layer_d1.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
s->msg_callback_arg);

if (SSL_is_init_finished(s) &&
(s->options & SSL_OP_NO_RENEGOTIATION) == 0 &&
!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
!s->s3->renegotiate) {
s->d1->handshake_read_seq++;
Expand Down Expand Up @@ -678,6 +679,9 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
}
}
}
} else {
SSL3_RECORD_set_length(rr, 0);
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
}
/*
* we either finished a handshake or ignored the request, now try
Expand All @@ -692,11 +696,13 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
*/
if (s->server
&& SSL_is_init_finished(s)
&& !s->s3->send_connection_binding
&& s->rlayer.d->handshake_fragment_len >= DTLS1_HM_HEADER_LENGTH
&& s->rlayer.d->handshake_fragment[0] == SSL3_MT_CLIENT_HELLO
&& s->s3->previous_client_finished_len != 0
&& (s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0) {
&& ((!s->s3->send_connection_binding
&& (s->options
& SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0)
|| (s->options & SSL_OP_NO_RENEGOTIATION) != 0)) {
s->rlayer.d->handshake_fragment_len = 0;
SSL3_RECORD_set_length(rr, 0);
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
Expand Down
10 changes: 6 additions & 4 deletions ssl/record/rec_layer_s3.c
Original file line number Diff line number Diff line change
Expand Up @@ -1284,8 +1284,8 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
s->rlayer.handshake_fragment, 4, s,
s->msg_callback_arg);

if (SSL_is_init_finished(s) &&
(s->options & SSL_OP_NO_RENEGOTIATION) == 0 &&
!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
!s->s3->renegotiate) {
ssl3_renegotiate(s);
Expand Down Expand Up @@ -1319,7 +1319,7 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
SSL3_RECORD_set_read(rr);
}
} else {
/* Does this ever happen? */
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
SSL3_RECORD_set_read(rr);
}
/*
Expand All @@ -1334,12 +1334,14 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
*/
if (s->server
&& SSL_is_init_finished(s)
&& !s->s3->send_connection_binding
&& s->version > SSL3_VERSION
&& s->rlayer.handshake_fragment_len >= SSL3_HM_HEADER_LENGTH
&& s->rlayer.handshake_fragment[0] == SSL3_MT_CLIENT_HELLO
&& s->s3->previous_client_finished_len != 0
&& (s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0) {
&& ((!s->s3->send_connection_binding
&& (s->options
& SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0)
|| (s->options & SSL_OP_NO_RENEGOTIATION) != 0)) {
SSL3_RECORD_set_length(rr, 0);
SSL3_RECORD_set_read(rr);
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
Expand Down
4 changes: 4 additions & 0 deletions ssl/ssl_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
SSL_FLAG_TBL("UnsafeLegacyRenegotiation",
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION),
SSL_FLAG_TBL_INV("EncryptThenMac", SSL_OP_NO_ENCRYPT_THEN_MAC),
SSL_FLAG_TBL("NoRenegotiation", SSL_OP_NO_RENEGOTIATION),
};
if (value == NULL)
return -3;
Expand Down Expand Up @@ -543,6 +544,7 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
SSL_CONF_CMD_SWITCH("serverpref", SSL_CONF_FLAG_SERVER),
SSL_CONF_CMD_SWITCH("legacy_renegotiation", 0),
SSL_CONF_CMD_SWITCH("legacy_server_connect", SSL_CONF_FLAG_SERVER),
SSL_CONF_CMD_SWITCH("no_renegotiation", 0),
SSL_CONF_CMD_SWITCH("no_resumption_on_reneg", SSL_CONF_FLAG_SERVER),
SSL_CONF_CMD_SWITCH("no_legacy_server_connect", SSL_CONF_FLAG_SERVER),
SSL_CONF_CMD_SWITCH("strict", 0),
Expand Down Expand Up @@ -602,6 +604,8 @@ static const ssl_switch_tbl ssl_cmd_switches[] = {
{SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION, 0},
/* legacy_server_connect */
{SSL_OP_LEGACY_SERVER_CONNECT, 0},
/* no_renegotiation */
{SSL_OP_NO_RENEGOTIATION, 0},
/* no_resumption_on_reneg */
{SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION, 0},
/* no_legacy_server_connect */
Expand Down
3 changes: 3 additions & 0 deletions ssl/ssl_err.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ static ERR_STRING_DATA SSL_str_functs[] = {
"ssl_parse_serverhello_use_srtp_ext"},
{ERR_FUNC(SSL_F_SSL_PEEK), "SSL_peek"},
{ERR_FUNC(SSL_F_SSL_READ), "SSL_read"},
{ERR_FUNC(SSL_F_SSL_RENEGOTIATE), "SSL_renegotiate"},
{ERR_FUNC(SSL_F_SSL_RENEGOTIATE_ABBREVIATED),
"SSL_renegotiate_abbreviated"},
{ERR_FUNC(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT),
"ssl_scan_clienthello_tlsext"},
{ERR_FUNC(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT),
Expand Down
10 changes: 10 additions & 0 deletions ssl/ssl_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1793,6 +1793,11 @@ int SSL_shutdown(SSL *s)

int SSL_renegotiate(SSL *s)
{
if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
SSLerr(SSL_F_SSL_RENEGOTIATE, SSL_R_NO_RENEGOTIATION);
return 0;
}

if (s->renegotiate == 0)
s->renegotiate = 1;

Expand All @@ -1803,6 +1808,11 @@ int SSL_renegotiate(SSL *s)

int SSL_renegotiate_abbreviated(SSL *s)
{
if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
SSLerr(SSL_F_SSL_RENEGOTIATE_ABBREVIATED, SSL_R_NO_RENEGOTIATION);
return 0;
}

if (s->renegotiate == 0)
s->renegotiate = 1;

Expand Down
8 changes: 8 additions & 0 deletions ssl/statem/statem.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,14 @@ static int state_machine(SSL *s, int server)
if (server) {
if (st->state != MSG_FLOW_RENEGOTIATE) {
s->ctx->stats.sess_accept++;
} else if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
/*
* Shouldn't happen? The record layer should have prevented this
*/
SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
ossl_statem_set_error(s);
goto end;
} else if (!s->s3->send_connection_binding &&
!(s->options &
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
Expand Down
1 change: 1 addition & 0 deletions ssl/t1_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
if (s->s3->send_connection_binding) {
int el;

/* Still add this even if SSL_OP_NO_RENEGOTIATION is set */
if (!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) {
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
return NULL;
Expand Down
29 changes: 18 additions & 11 deletions test/handshake_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,11 @@ static void do_handshake_step(PEER *peer)
{
int ret;

TEST_check(peer->status == PEER_RETRY);
if (peer->status != PEER_RETRY) {
peer->status = PEER_ERROR;
return;
}

ret = SSL_do_handshake(peer->ssl);

if (ret == 1) {
Expand Down Expand Up @@ -588,6 +592,17 @@ static void do_reneg_setup_step(const SSL_TEST_CTX *test_ctx, PEER *peer)
int ret;
char buf;

if (peer->status == PEER_SUCCESS) {
/*
* We are a client that succeeded this step previously, but the server
* wanted to retry. Probably there is a no_renegotiation warning alert
* waiting for us. Attempt to continue the handshake.
*/
peer->status = PEER_RETRY;
do_handshake_step(peer);
return;
}

TEST_check(peer->status == PEER_RETRY);
TEST_check(test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_SERVER
|| test_ctx->handshake_mode == SSL_TEST_HANDSHAKE_RENEG_CLIENT);
Expand Down Expand Up @@ -807,16 +822,8 @@ static handshake_status_t handshake_status(peer_status_t last_status,
break;

case PEER_RETRY:
if (previous_status == PEER_RETRY) {
/* Neither peer is done. */
return HANDSHAKE_RETRY;
} else {
/*
* Deadlock: second peer is waiting for more input while first
* peer thinks they're done (no more input is coming).
*/
return INTERNAL_ERROR;
}
return HANDSHAKE_RETRY;

case PEER_ERROR:
switch (previous_status) {
case PEER_SUCCESS:
Expand Down
Loading

0 comments on commit 6e127fd

Please sign in to comment.