summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES4
-rw-r--r--include/openssl/ssl.h8
-rw-r--r--ssl/d1_lib.c38
-rw-r--r--ssl/methods.c54
-rw-r--r--ssl/s3_lib.c27
-rw-r--r--ssl/ssl_cert.c24
-rw-r--r--ssl/ssl_ciph.c8
-rw-r--r--ssl/ssl_conf.c32
-rw-r--r--ssl/ssl_err.c14
-rw-r--r--ssl/ssl_lib.c18
-rw-r--r--ssl/ssl_locl.h32
-rw-r--r--ssl/statem/statem.c15
-rw-r--r--ssl/statem/statem_clnt.c246
-rw-r--r--ssl/statem/statem_lib.c385
-rw-r--r--ssl/statem/statem_srvr.c112
-rw-r--r--ssl/t1_lib.c5
16 files changed, 543 insertions, 479 deletions
diff --git a/CHANGES b/CHANGES
index b0331b2594..b4cc2d4c93 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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.
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index a0d66fa0c4..0d22ab7716 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -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
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index a510b5bebe..3cd4b786e4 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -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;
}
diff --git a/ssl/methods.c b/ssl/methods.c
index ef20c9ca3e..7a8bb11b77 100644
--- a/ssl/methods.c
+++ b/ssl/methods.c
@@ -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,
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index e3e4fd34f8..d307ec05d6 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -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;
}
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index f01d3a7835..597de0ad6c 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -1084,15 +1084,21 @@ static int ssl_security_default_callback(SSL *s, SSL_CTX *ctx, int op,
break;
}
case SSL_SECOP_VERSION:
- /* SSLv3 not allowed on level 2 */
- if (nid <= SSL3_VERSION && level >= 2)
- return 0;
- /* TLS v1.1 and above only for level 3 */
- if (nid <= TLS1_VERSION && level >= 3)
- return 0;
- /* TLS v1.2 only for level 4 and above */
- if (nid <= TLS1_1_VERSION && level >= 4)
- return 0;
+ if (!SSL_IS_DTLS(s)) {
+ /* SSLv3 not allowed at level 2 */
+ if (nid <= SSL3_VERSION && level >= 2)
+ return 0;
+ /* TLS v1.1 and above only for level 3 */
+ if (nid <= TLS1_VERSION && level >= 3)
+ return 0;
+ /* TLS v1.2 only for level 4 and above */
+ if (nid <= TLS1_1_VERSION && level >= 4)
+ return 0;
+ } else {
+ /* DTLS v1.2 only for level 4 and above */
+ if (DTLS_VERSION_LT(nid, DTLS1_2_VERSION) && level >= 4)
+ return 0;
+ }
break;
case SSL_SECOP_COMPRESSION:
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 65a5bb6c96..a15248d41b 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -1349,12 +1349,8 @@ static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c,
/* Check version: if TLS 1.2 ciphers allowed we can use Suite B */
if (!(meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS)) {
- if (meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS)
- SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST,
- SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE);
- else
- SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST,
- SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE);
+ SSLerr(SSL_F_CHECK_SUITEB_CIPHER_LIST,
+ SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE);
return 0;
}
# ifndef OPENSSL_NO_EC
diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c
index 1e14a4497e..9529d30842 100644
--- a/ssl/ssl_conf.c
+++ b/ssl/ssl_conf.c
@@ -347,6 +347,22 @@ static int protocol_from_string(const char *value)
return -1;
}
+static int min_max_proto(SSL_CONF_CTX *cctx, const char *value, int *bound)
+{
+ int method_version;
+ int new_version;
+
+ if (cctx->ctx != NULL)
+ method_version = cctx->ctx->method->version;
+ else if (cctx->ssl != NULL)
+ method_version = cctx->ssl->ctx->method->version;
+ else
+ return 0;
+ if ((new_version = protocol_from_string(value)) < 0)
+ return 0;
+ return ssl_set_version_bound(method_version, new_version, bound);
+}
+
/*
* cmd_MinProtocol - Set min protocol version
* @cctx: config structure to save settings in
@@ -356,13 +372,7 @@ static int protocol_from_string(const char *value)
*/
static int cmd_MinProtocol(SSL_CONF_CTX *cctx, const char *value)
{
- int version = protocol_from_string(value);
-
- if (version < 0)
- return 0;
-
- *(cctx->min_version) = version;
- return 1;
+ return min_max_proto(cctx, value, cctx->min_version);
}
/*
@@ -374,13 +384,7 @@ static int cmd_MinProtocol(SSL_CONF_CTX *cctx, const char *value)
*/
static int cmd_MaxProtocol(SSL_CONF_CTX *cctx, const char *value)
{
- int version = protocol_from_string(value);
-
- if (version < 0)
- return 0;
-
- *(cctx->max_version) = version;
- return 1;
+ return min_max_proto(cctx, value, cctx->max_version);
}
static int cmd_Options(SSL_CONF_CTX *cctx, const char *value)
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 0c40b7b3ec..d9dbf99391 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -314,7 +314,6 @@ static ERR_STRING_DATA SSL_str_functs[] = {
{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT),
"SSL_set_session_ticket_ext"},
{ERR_FUNC(SSL_F_SSL_SET_TRUST), "SSL_set_trust"},
- {ERR_FUNC(SSL_F_SSL_SET_VERSION), "SSL_SET_VERSION"},
{ERR_FUNC(SSL_F_SSL_SET_WFD), "SSL_set_wfd"},
{ERR_FUNC(SSL_F_SSL_SHUTDOWN), "SSL_shutdown"},
{ERR_FUNC(SSL_F_SSL_SRP_CTX_INIT), "SSL_SRP_CTX_init"},
@@ -416,6 +415,10 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
{ERR_REASON(SSL_R_APP_DATA_IN_HANDSHAKE), "app data in handshake"},
{ERR_REASON(SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT),
"attempt to reuse session in different context"},
+ {ERR_REASON(SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE),
+ "at least TLS 1.0 needed in FIPS mode"},
+ {ERR_REASON(SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE),
+ "at least (D)TLS 1.2 needed in Suite B mode"},
{ERR_REASON(SSL_R_BAD_ALERT_RECORD), "bad alert record"},
{ERR_REASON(SSL_R_BAD_CHANGE_CIPHER_SPEC), "bad change cipher spec"},
{ERR_REASON(SSL_R_BAD_DATA), "bad data"},
@@ -603,14 +606,6 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
"old session cipher not returned"},
{ERR_REASON(SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED),
"old session compression algorithm not returned"},
- {ERR_REASON(SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE),
- "only DTLS 1.2 allowed in Suite B mode"},
- {ERR_REASON(SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE),
- "only TLS 1.2 allowed in Suite B mode"},
- {ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE),
- "only tls allowed in fips mode"},
- {ERR_REASON(SSL_R_OPAQUE_PRF_INPUT_TOO_LONG),
- "opaque PRF input too long"},
{ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG), "packet length too long"},
{ERR_REASON(SSL_R_PARSE_TLSEXT), "parse tlsext"},
{ERR_REASON(SSL_R_PATH_TOO_LONG), "path too long"},
@@ -794,6 +789,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
{ERR_REASON(SSL_R_UNSUPPORTED_SSL_VERSION), "unsupported ssl version"},
{ERR_REASON(SSL_R_UNSUPPORTED_STATUS_TYPE), "unsupported status type"},
{ERR_REASON(SSL_R_USE_SRTP_NOT_NEGOTIATED), "use srtp not negotiated"},
+ {ERR_REASON(SSL_R_VERSION_TOO_HIGH), "version too high"},
{ERR_REASON(SSL_R_VERSION_TOO_LOW), "version too low"},
{ERR_REASON(SSL_R_WRONG_CERTIFICATE_TYPE), "wrong certificate type"},
{ERR_REASON(SSL_R_WRONG_CIPHER_RETURNED), "wrong cipher returned"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index cfc73de9ca..760014d739 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1201,11 +1201,11 @@ long SSL_ctrl(SSL *s, int cmd, long larg, void *parg)
else
return 0;
case SSL_CTRL_SET_MIN_PROTO_VERSION:
- s->min_proto_version = larg;
- return 1;
+ return ssl_set_version_bound(s->ctx->method->version, (int)larg,
+ &s->min_proto_version);
case SSL_CTRL_SET_MAX_PROTO_VERSION:
- s->max_proto_version = larg;
- return 1;
+ return ssl_set_version_bound(s->ctx->method->version, (int)larg,
+ &s->max_proto_version);
default:
return (s->method->ssl_ctrl(s, cmd, larg, parg));
}
@@ -1323,11 +1323,11 @@ long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
case SSL_CTRL_CLEAR_CERT_FLAGS:
return (ctx->cert->cert_flags &= ~larg);
case SSL_CTRL_SET_MIN_PROTO_VERSION:
- ctx->min_proto_version = larg;
- return 1;
+ return ssl_set_version_bound(ctx->method->version, (int)larg,
+ &ctx->min_proto_version);
case SSL_CTRL_SET_MAX_PROTO_VERSION:
- ctx->max_proto_version = larg;
- return 1;
+ return ssl_set_version_bound(ctx->method->version, (int)larg,
+ &ctx->max_proto_version);
default:
return (ctx->method->ssl_ctx_ctrl(ctx, cmd, larg, parg));
}
@@ -1795,7 +1795,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
}
if (FIPS_mode() && (meth->version < TLS1_VERSION)) {
- SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE);
+ SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE);
return NULL;
}
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 9482fc91ad..7e07297f2f 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -471,8 +471,8 @@
* flags because it may not be set to correct version yet.
*/
# define SSL_CLIENT_USE_TLS1_2_CIPHERS(s) \
- ((SSL_IS_DTLS(s) && s->client_version <= DTLS1_2_VERSION) || \
- (!SSL_IS_DTLS(s) && s->client_version >= TLS1_2_VERSION))
+ ((!SSL_IS_DTLS(s) && s->client_version >= TLS1_2_VERSION) || \
+ (SSL_IS_DTLS(s) && DTLS_VERSION_GE(s->client_version, DTLS1_2_VERSION)))
# ifdef TLSEXT_TYPE_encrypt_then_mac
# define SSL_USE_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC)
@@ -535,6 +535,8 @@ struct ssl_cipher_st {
/* Used to hold SSL/TLS functions */
struct ssl_method_st {
int version;
+ unsigned flags;
+ unsigned long mask;
int (*ssl_new) (SSL *s);
void (*ssl_clear) (SSL *s);
void (*ssl_free) (SSL *s);
@@ -1685,12 +1687,20 @@ extern const SSL3_ENC_METHOD SSLv3_enc_data;
extern const SSL3_ENC_METHOD DTLSv1_enc_data;
extern const SSL3_ENC_METHOD DTLSv1_2_enc_data;
-# define IMPLEMENT_tls_meth_func(version, func_name, s_accept, s_connect, \
- s_get_meth, enc_data) \
+/*
+ * Flags for SSL methods
+ */
+#define SSL_METHOD_NO_FIPS (1U<<0)
+#define SSL_METHOD_NO_SUITEB (1U<<1)
+
+# define IMPLEMENT_tls_meth_func(version, flags, mask, func_name, s_accept, \
+ s_connect, s_get_meth, enc_data) \
const SSL_METHOD *func_name(void) \
{ \
static const SSL_METHOD func_name##_data= { \
version, \
+ flags, \
+ mask, \
tls1_new, \
tls1_clear, \
tls1_free, \
@@ -1727,6 +1737,8 @@ const SSL_METHOD *func_name(void) \
{ \
static const SSL_METHOD func_name##_data= { \
SSL3_VERSION, \
+ SSL_METHOD_NO_FIPS | SSL_METHOD_NO_SUITEB, \
+ SSL_OP_NO_SSLv3, \
ssl3_new, \
ssl3_clear, \
ssl3_free, \
@@ -1758,12 +1770,14 @@ const SSL_METHOD *func_name(void) \
return &func_name##_data; \
}
-# define IMPLEMENT_dtls1_meth_func(version, func_name, s_accept, s_connect, \
- s_get_meth, enc_data) \
+# define IMPLEMENT_dtls1_meth_func(version, flags, mask, func_name, s_accept, \
+ s_connect, s_get_meth, enc_data) \
const SSL_METHOD *func_name(void) \
{ \
static const SSL_METHOD func_name##_data= { \
version, \
+ flags, \
+ mask, \
dtls1_new, \
dtls1_clear, \
dtls1_free, \
@@ -1911,6 +1925,12 @@ __owur int ssl3_handshake_write(SSL *s);
__owur int ssl_allow_compression(SSL *s);
+__owur int ssl_set_client_hello_version(SSL *s);
+__owur int ssl_check_version_downgrade(SSL *s);
+__owur int ssl_set_version_bound(int method_version, int version, int *bound);
+__owur int ssl_choose_server_version(SSL *s);
+__owur int ssl_choose_client_version(SSL *s, int version);
+
__owur long tls1_default_timeout(void);
__owur int dtls1_do_write(SSL *s, int type);
void dtls1_set_message_header(SSL *s,
diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c
index bc3fc54fab..a03fe32083 100644
--- a/ssl/statem/statem.c
+++ b/ssl/statem/statem.c
@@ -261,7 +261,8 @@ static void (*get_callback(SSL *s))(const SSL *, int, int)
* 1: Success
* <=0: NBIO or error
*/
-static int state_machine(SSL *s, int server) {
+static int state_machine(SSL *s, int server)
+{
BUF_MEM *buf = NULL;
unsigned long Time = (unsigned long)time(NULL);
void (*cb) (const SSL *ssl, int type, int val) = NULL;
@@ -336,19 +337,15 @@ static int state_machine(SSL *s, int server) {
goto end;
}
} else {
- if ((s->version >> 8) != SSL3_VERSION_MAJOR
- && s->version != TLS_ANY_VERSION) {
+ if ((s->version >> 8) != SSL3_VERSION_MAJOR) {
SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
goto end;
}
}
- if (!SSL_IS_DTLS(s)) {
- if (s->version != TLS_ANY_VERSION &&
- !ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
- SSLerr(SSL_F_STATE_MACHINE, SSL_R_VERSION_TOO_LOW);
- goto end;
- }
+ if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
+ SSLerr(SSL_F_STATE_MACHINE, SSL_R_VERSION_TOO_LOW);
+ goto end;
}
if (s->init_buf == NULL) {
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 26acdc5488..cfbfa5f8c3 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -166,7 +166,6 @@
static ossl_inline int cert_req_allowed(SSL *s);
static int key_exchange_expected(SSL *s);
-static int ssl_set_version(SSL *s);
static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b);
static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
unsigned char *p);
@@ -800,128 +799,12 @@ WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst)
return WORK_ERROR;
}
-/*
- * Work out what version we should be using for the initial ClientHello if
- * the version is currently set to (D)TLS_ANY_VERSION.
- * Returns 1 on success
- * Returns 0 on error
- */
-static int ssl_set_version(SSL *s)
-{
- unsigned long mask, options = s->options;
-
- if (s->method->version == TLS_ANY_VERSION) {
- /*
- * SSL_OP_NO_X disables all protocols above X *if* there are
- * some protocols below X enabled. This is required in order
- * to maintain "version capability" vector contiguous. So
- * that if application wants to disable TLS1.0 in favour of
- * TLS1>=1, it would be insufficient to pass SSL_NO_TLSv1, the
- * answer is SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3.
- */
- mask = SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1
-#if !defined(OPENSSL_NO_SSL3)
- | SSL_OP_NO_SSLv3
-#endif
- ;
-#if !defined(OPENSSL_NO_TLS1_2_CLIENT)
- if (options & SSL_OP_NO_TLSv1_2) {
- if ((options & mask) != mask) {
- s->version = TLS1_1_VERSION;
- } else {
- SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_NO_PROTOCOLS_AVAILABLE);
- return 0;
- }
- } else {
- s->version = TLS1_2_VERSION;
- }
-#else
- if ((options & mask) == mask) {
- SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_NO_PROTOCOLS_AVAILABLE);
- return 0;
- }
- s->version = TLS1_1_VERSION;
-#endif
-
- mask &= ~SSL_OP_NO_TLSv1_1;
- if ((options & SSL_OP_NO_TLSv1_1) && (options & mask) != mask)
- s->version = TLS1_VERSION;
- mask &= ~SSL_OP_NO_TLSv1;
-#if !defined(OPENSSL_NO_SSL3)
- if ((options & SSL_OP_NO_TLSv1) && (options & mask) != mask)
- s->version = SSL3_VERSION;
-#endif
-
- if (s->max_proto_version != 0 && (s->version > s->max_proto_version))
- s->version = s->max_proto_version;
- if (s->version < s->min_proto_version)
- {
- SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_NO_PROTOCOLS_AVAILABLE);
- return 0;
- }
-
- if (s->version != TLS1_2_VERSION && tls1_suiteb(s)) {
- SSLerr(SSL_F_SSL_SET_VERSION,
- SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE);
- return 0;
- }
-
- if (s->version == SSL3_VERSION && FIPS_mode()) {
- SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE);
- return 0;
- }
-
- } else if (s->method->version == DTLS_ANY_VERSION) {
- int max_version = DTLS_MAX_VERSION;
- int min_version = DTLS_MIN_VERSION;
-
- if (s->max_proto_version != 0)
- max_version = s->max_proto_version;
- if (s->min_proto_version != 0)
- min_version = s->min_proto_version;
-
- /* If DTLS 1.2 disabled correct the version number */
- if (options & SSL_OP_NO_DTLSv1_2
- || DTLS_VERSION_GT(DTLS1_2_VERSION, max_version)) {
- if (tls1_suiteb(s)) {
- SSLerr(SSL_F_SSL_SET_VERSION,
- SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE);
- return 0;
- }
- /*
- * Disabling all versions is silly: return an error.
- */
- if (options & SSL_OP_NO_DTLSv1
- || DTLS_VERSION_GT(min_version, DTLS1_VERSION)) {
- SSLerr(SSL_F_SSL_SET_VERSION, SSL_R_WRONG_SSL_VERSION);
- return 0;
- }
- /*
- * Update method so we don't use any DTLS 1.2 features.
- */
- s->method = DTLSv1_client_method();
- s->version = DTLS1_VERSION;
- } else {
- /*
- * We only support one version: update method
- */
- if (options & SSL_OP_NO_DTLSv1
- || DTLS_VERSION_GE(min_version, DTLS1_2_VERSION))
- s->method = DTLSv1_2_client_method();
- s->version = DTLS1_2_VERSION;
- }
- }
-
- s->client_version = s->version;
-
- return 1;
-