Commit 4fa52141 authored by Viktor Dukhovni's avatar Viktor Dukhovni
Browse files

Protocol version selection and negotiation rewrite



The protocol selection code is now consolidated in a few consecutive
short functions in a single file and is table driven.  Protocol-specific
constraints that influence negotiation are moved into the flags
field of the method structure.  The same protocol version constraints
are now applied in all code paths.  It is now much easier to add
new protocol versions without reworking the protocol selection
logic.

In the presence of "holes" in the list of enabled client protocols
we no longer select client protocols below the hole based on a
subset of the constraints and then fail shortly after when it is
found that these don't meet the remaining constraints (suiteb, FIPS,
security level, ...).  Ideally, with the new min/max controls users
will be less likely to create "holes" in the first place.

Reviewed-by: default avatarKurt Roeckx <kurt@openssl.org>
parent 57ce7b61
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -9,7 +9,9 @@
     SSL_set_max_proto_version(), or via the SSL_CONF's MinProtocol and
     MaxProtcol.  It's recommended to use the new APIs to disable
     protocols instead of disabling individual protocols using
     SSL_set_options() or SSL_CONF's Protocol.
     SSL_set_options() or SSL_CONF's Protocol.  This change also
     removes support for disabling TLS 1.2 in the OpenSSL TLS
     client at compile time by defining OPENSSL_NO_TLS1_2_CLIENT.
     [Kurt Roeckx]

  *) Support for ChaCha20 and Poly1305 added to libcrypto and libssl.
+3 −5
Original line number Diff line number Diff line
@@ -1217,7 +1217,6 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
# define SSL_CTRL_SELECT_CURRENT_CERT            116
# define SSL_CTRL_SET_CURRENT_CERT               117
# define SSL_CTRL_SET_DH_AUTO                    118
# define SSL_CTRL_CHECK_PROTO_VERSION            119
# define DTLS_CTRL_SET_LINK_MTU                  120
# define DTLS_CTRL_GET_LINK_MIN_MTU              121
# define SSL_CTRL_GET_EXTMS_SUPPORT              122
@@ -2099,7 +2098,6 @@ void ERR_load_SSL_strings(void);
# define SSL_F_SSL_SET_SESSION_ID_CONTEXT                 218
# define SSL_F_SSL_SET_SESSION_TICKET_EXT                 294
# define SSL_F_SSL_SET_TRUST                              228
# define SSL_F_SSL_SET_VERSION                            347
# define SSL_F_SSL_SET_WFD                                196
# define SSL_F_SSL_SHUTDOWN                               224
# define SSL_F_SSL_SRP_CTX_INIT                           313
@@ -2170,6 +2168,8 @@ void ERR_load_SSL_strings(void);
/* Reason codes. */
# define SSL_R_APP_DATA_IN_HANDSHAKE                      100
# define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
# define SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE       143
# define SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE     158
# define SSL_R_BAD_ALERT_RECORD                           101
# define SSL_R_BAD_CHANGE_CIPHER_SPEC                     103
# define SSL_R_BAD_DATA                                   390
@@ -2323,9 +2323,6 @@ void ERR_load_SSL_strings(void);
# define SSL_R_NULL_SSL_METHOD_PASSED                     196
# define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED            197
# define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344
# define SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE       387
# define SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE        379
# define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE              297
# define SSL_R_OPAQUE_PRF_INPUT_TOO_LONG                  327
# define SSL_R_PACKET_LENGTH_TOO_LONG                     198
# define SSL_R_PARSE_TLSEXT                               227
@@ -2443,6 +2440,7 @@ void ERR_load_SSL_strings(void);
# define SSL_R_UNSUPPORTED_SSL_VERSION                    259
# define SSL_R_UNSUPPORTED_STATUS_TYPE                    329
# define SSL_R_USE_SRTP_NOT_NEGOTIATED                    369
# define SSL_R_VERSION_TOO_HIGH                           166
# define SSL_R_VERSION_TOO_LOW                            396
# define SSL_R_WRONG_CERTIFICATE_TYPE                     383
# define SSL_R_WRONG_CIPHER_RETURNED                      261
+3 −35
Original line number Diff line number Diff line
@@ -235,7 +235,7 @@ void dtls1_clear(SSL *s)
    if (s->options & SSL_OP_CISCO_ANYCONNECT)
        s->client_version = s->version = DTLS1_BAD_VER;
    else if (s->method->version == DTLS_ANY_VERSION)
        s->version = DTLS1_2_VERSION;
        s->version = DTLS_MAX_VERSION;
    else
        s->version = s->method->version;
}
@@ -256,38 +256,6 @@ long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
    case DTLS_CTRL_LISTEN:
        ret = dtls1_listen(s, parg);
        break;
    case SSL_CTRL_CHECK_PROTO_VERSION:
        /*
         * For library-internal use; checks that the current protocol is the
         * is the highest enabled version.
         */
        if (s->max_proto_version == 0 && s->version == DTLS_MAX_VERSION)
            return 1;
        if (s->max_proto_version != 0 && s->version == s->max_proto_version)
            return 1;
        /* We're not limited by the max_proto_version but might still have
         * other reasons why we use an older version like not using a
         * version-flexible SSL_METHOD.  Check s->ctx->method as version
         * negotiation may have changed s->method.
         * This check can be removed when we only have version-flexible
         * SSL_METHODs
         */
        if (s->version == s->ctx->method->version)
            return 1;
        /*
         * Apparently we're using a version-flexible SSL_METHOD (not at its
         * highest protocol version, not limited by max_proto_version).
         */
        if (s->ctx->method->version == DTLS_method()->version) {
#if DTLS_MAX_VERSION != DTLS1_2_VERSION
# error Code needs update for DTLS_method() support beyond DTLS1_2_VERSION.
#endif
            if (!(s->options & SSL_OP_NO_DTLSv1_2))
                return s->version == DTLS1_2_VERSION;
            if (!(s->options & SSL_OP_NO_DTLSv1))
                return s->version == DTLS1_VERSION;
        }
        return 0;               /* Unexpected state; fail closed. */
    case DTLS_CTRL_SET_LINK_MTU:
        if (larg < (long)dtls1_link_min_mtu())
            return 0;
@@ -708,8 +676,8 @@ int dtls1_listen(SSL *s, struct sockaddr *client)
        /*
         * Verify client version is supported
         */
        if ((clientvers > (unsigned int)s->method->version &&
                              s->method->version != DTLS_ANY_VERSION)) {
        if (DTLS_VERSION_LT(clientvers, (unsigned int)s->method->version) &&
            s->method->version != DTLS_ANY_VERSION) {
            SSLerr(SSL_F_DTLS1_LISTEN, SSL_R_WRONG_VERSION_NUMBER);
            goto end;
        }
+33 −21
Original line number Diff line number Diff line
@@ -135,19 +135,23 @@ static const SSL_METHOD *tls1_get_method(int ver)
    return NULL;
}

IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, TLS_method,
IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0,
                        TLS_method,
                        ossl_statem_accept,
                        ossl_statem_connect, tls1_get_method, TLSv1_2_enc_data)

IMPLEMENT_tls_meth_func(TLS1_2_VERSION, TLSv1_2_method,
IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2,
                        TLSv1_2_method,
                        ossl_statem_accept,
                        ossl_statem_connect, tls1_get_method, TLSv1_2_enc_data)

IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_method,
IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1,
                        TLSv1_1_method,
                        ossl_statem_accept,
                        ossl_statem_connect, tls1_get_method, TLSv1_1_enc_data)

IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_method,
IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1,
                        TLSv1_method,
                        ossl_statem_accept,
                        ossl_statem_connect, tls1_get_method, TLSv1_enc_data)

@@ -178,22 +182,26 @@ static const SSL_METHOD *tls1_get_server_method(int ver)
    return NULL;
}

IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, TLS_server_method,
IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0,
                        TLS_server_method,
                        ossl_statem_accept,
                        ssl_undefined_function,
                        tls1_get_server_method, TLSv1_2_enc_data)

IMPLEMENT_tls_meth_func(TLS1_2_VERSION, TLSv1_2_server_method,
IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2,
                        TLSv1_2_server_method,
                        ossl_statem_accept,
                        ssl_undefined_function,
                        tls1_get_server_method, TLSv1_2_enc_data)

IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_server_method,
IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1,
                        TLSv1_1_server_method,
                        ossl_statem_accept,
                        ssl_undefined_function,
                        tls1_get_server_method, TLSv1_1_enc_data)

IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_server_method,
IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1,
                        TLSv1_server_method,
                        ossl_statem_accept,
                        ssl_undefined_function,
                        tls1_get_server_method, TLSv1_enc_data)
@@ -226,22 +234,26 @@ static const SSL_METHOD *tls1_get_client_method(int ver)
    return NULL;
}

IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, TLS_client_method,
IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, 0, 0,
                        TLS_client_method,
                        ssl_undefined_function,
                        ossl_statem_connect,
                        tls1_get_client_method, TLSv1_2_enc_data)

IMPLEMENT_tls_meth_func(TLS1_2_VERSION, TLSv1_2_client_method,
IMPLEMENT_tls_meth_func(TLS1_2_VERSION, 0, SSL_OP_NO_TLSv1_2,
                        TLSv1_2_client_method,
                        ssl_undefined_function,
                        ossl_statem_connect,
                        tls1_get_client_method, TLSv1_2_enc_data)

IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_client_method,
IMPLEMENT_tls_meth_func(TLS1_1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1_1,
                        TLSv1_1_client_method,
                        ssl_undefined_function,
                        ossl_statem_connect,
                        tls1_get_client_method, TLSv1_1_enc_data)

IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_client_method,
IMPLEMENT_tls_meth_func(TLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_TLSv1,
                        TLSv1_client_method,
                        ssl_undefined_function,
                        ossl_statem_connect,
                        tls1_get_client_method, TLSv1_enc_data)
@@ -268,19 +280,19 @@ static const SSL_METHOD *dtls1_get_method(int ver)
        return NULL;
}

IMPLEMENT_dtls1_meth_func(DTLS1_VERSION,
IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
                          DTLSv1_method,
                          ossl_statem_accept,
                          ossl_statem_connect,
                          dtls1_get_method, DTLSv1_enc_data)

IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION,
IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2,
                          DTLSv1_2_method,
                          ossl_statem_accept,
                          ossl_statem_connect,
                          dtls1_get_method, DTLSv1_2_enc_data)

IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION,
IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0,
                          DTLS_method,
                          ossl_statem_accept,
                          ossl_statem_connect,
@@ -303,19 +315,19 @@ static const SSL_METHOD *dtls1_get_server_method(int ver)
        return NULL;
}

IMPLEMENT_dtls1_meth_func(DTLS1_VERSION,
IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
                          DTLSv1_server_method,
                          ossl_statem_accept,
                          ssl_undefined_function,
                          dtls1_get_server_method, DTLSv1_enc_data)

IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION,
IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2,
                          DTLSv1_2_server_method,
                          ossl_statem_accept,
                          ssl_undefined_function,
                          dtls1_get_server_method, DTLSv1_2_enc_data)

IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION,
IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0,
                          DTLS_server_method,
                          ossl_statem_accept,
                          ssl_undefined_function,
@@ -338,19 +350,19 @@ static const SSL_METHOD *dtls1_get_client_method(int ver)
        return NULL;
}

IMPLEMENT_dtls1_meth_func(DTLS1_VERSION,
IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
                          DTLSv1_client_method,
                          ssl_undefined_function,
                          ossl_statem_connect,
                          dtls1_get_client_method, DTLSv1_enc_data)

IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION,
IMPLEMENT_dtls1_meth_func(DTLS1_2_VERSION, 0, SSL_OP_NO_DTLSv1_2,
                          DTLSv1_2_client_method,
                          ssl_undefined_function,
                          ossl_statem_connect,
                          dtls1_get_client_method, DTLSv1_2_enc_data)

IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION,
IMPLEMENT_dtls1_meth_func(DTLS_ANY_VERSION, 0, 0,
                          DTLS_client_method,
                          ssl_undefined_function,
                          ossl_statem_connect,
+0 −27
Original line number Diff line number Diff line
@@ -3777,33 +3777,6 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
        }
#endif

    case SSL_CTRL_CHECK_PROTO_VERSION:
        /*
         * For library-internal use; checks that the current protocol is the
         * highest enabled version (according to s->ctx->method, as version
         * negotiation may have changed s->method).
         */
        if (s->version == s->ctx->method->version)
            return 1;
        /*
         * Apparently we're using a version-flexible SSL_METHOD (not at its
         * highest protocol version).
         */
        if (s->ctx->method->version == TLS_method()->version) {
#if TLS_MAX_VERSION != TLS1_2_VERSION
# error Code needs update for TLS_method() support beyond TLS1_2_VERSION.
#endif
            if (!(s->options & SSL_OP_NO_TLSv1_2))
                return s->version == TLS1_2_VERSION;
            if (!(s->options & SSL_OP_NO_TLSv1_1))
                return s->version == TLS1_1_VERSION;
            if (!(s->options & SSL_OP_NO_TLSv1))
                return s->version == TLS1_VERSION;
            if (!(s->options & SSL_OP_NO_SSLv3))
                return s->version == SSL3_VERSION;
        }
        return 0;               /* Unexpected state; fail closed. */

    default:
        break;
    }
Loading