diff options
author | Kurt Roeckx <kurt@roeckx.be> | 2015-12-06 17:56:41 +0100 |
---|---|---|
committer | Viktor Dukhovni <openssl-users@dukhovni.org> | 2016-01-02 10:47:52 -0500 |
commit | 7946ab33cecce60afcc00afc8fc18f31f9e66bff (patch) | |
tree | fa178fbc42a649e87e201820cc11796dc3c7d6de /ssl/statem | |
parent | 1e0784ff95cd69090e26e2205bfec6305038db56 (diff) |
Add support for minimum and maximum protocol version
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Diffstat (limited to 'ssl/statem')
-rw-r--r-- | ssl/statem/statem_clnt.c | 64 | ||||
-rw-r--r-- | ssl/statem/statem_srvr.c | 41 |
2 files changed, 86 insertions, 19 deletions
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index d168b19cb8..26acdc5488 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -852,6 +852,14 @@ static int ssl_set_version(SSL *s) 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); @@ -864,9 +872,17 @@ static int ssl_set_version(SSL *s) } } else if (s->method->version == DTLS_ANY_VERSION) { - /* Determine which DTLS version to use */ + 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) { + 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); @@ -875,7 +891,8 @@ static int ssl_set_version(SSL *s) /* * Disabling all versions is silly: return an error. */ - if (options & SSL_OP_NO_DTLSv1) { + 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; } @@ -888,7 +905,8 @@ static int ssl_set_version(SSL *s) /* * We only support one version: update method */ - if (options & SSL_OP_NO_DTLSv1) + 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; } @@ -1129,6 +1147,10 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) if (s->method->version == TLS_ANY_VERSION) { unsigned int sversion; + int max_version = TLS_MAX_VERSION; + + if (s->max_proto_version != 0) + max_version = s->max_proto_version; if (!PACKET_get_net_2(pkt, &sversion)) { al = SSL_AD_DECODE_ERROR; @@ -1140,7 +1162,9 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) #error Code needs updating for new TLS version #endif #ifndef OPENSSL_NO_SSL3 - if ((sversion == SSL3_VERSION) && !(s->options & SSL_OP_NO_SSLv3)) { + if ((sversion == SSL3_VERSION) && !(s->options & SSL_OP_NO_SSLv3) && + (s->min_proto_version <= SSL3_VERSION) && + (max_version >= SSL3_VERSION)) { if (FIPS_mode()) { SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE); @@ -1150,13 +1174,19 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) s->method = SSLv3_client_method(); } else #endif - if ((sversion == TLS1_VERSION) && !(s->options & SSL_OP_NO_TLSv1)) { + if ((sversion == TLS1_VERSION) && !(s->options & SSL_OP_NO_TLSv1) && + (s->min_proto_version <= TLS1_VERSION) && + (max_version >= TLS1_VERSION)) { s->method = TLSv1_client_method(); } else if ((sversion == TLS1_1_VERSION) && - !(s->options & SSL_OP_NO_TLSv1_1)) { + !(s->options & SSL_OP_NO_TLSv1_1) && + (s->min_proto_version <= TLS1_1_VERSION) && + (max_version >= TLS1_1_VERSION)) { s->method = TLSv1_1_client_method(); } else if ((sversion == TLS1_2_VERSION) && - !(s->options & SSL_OP_NO_TLSv1_2)) { + !(s->options & SSL_OP_NO_TLSv1_2) && + (s->min_proto_version <= TLS1_2_VERSION) && + (max_version >= TLS1_2_VERSION)) { s->method = TLSv1_2_client_method(); } else { SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_UNSUPPORTED_PROTOCOL); @@ -1165,7 +1195,8 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) } s->session->ssl_version = s->version = s->method->version; - if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) { + if ((s->version < s->min_proto_version) + || !ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) { SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_VERSION_TOO_LOW); al = SSL_AD_PROTOCOL_VERSION; goto f_err; @@ -1174,6 +1205,13 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) /* Work out correct protocol version to use */ unsigned int hversion; int options; + 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 (!PACKET_get_net_2(pkt, &hversion)) { al = SSL_AD_DECODE_ERROR; @@ -1182,7 +1220,9 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) } options = s->options; - if (hversion == DTLS1_2_VERSION && !(options & SSL_OP_NO_DTLSv1_2)) + if (hversion == DTLS1_2_VERSION && !(options & SSL_OP_NO_DTLSv1_2) && + DTLS_VERSION_LE(min_version, DTLS1_2_VERSION) && + DTLS_VERSION_GE(max_version, DTLS1_2_VERSION)) s->method = DTLSv1_2_client_method(); else if (tls1_suiteb(s)) { SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, @@ -1190,7 +1230,9 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt) s->version = hversion; al = SSL_AD_PROTOCOL_VERSION; goto f_err; - } else if (hversion == DTLS1_VERSION && !(options & SSL_OP_NO_DTLSv1)) + } else if (hversion == DTLS1_VERSION && !(options & SSL_OP_NO_DTLSv1) && + DTLS_VERSION_LE(min_version, DTLS1_VERSION) && + DTLS_VERSION_GE(max_version, DTLS1_VERSION)) s->method = DTLSv1_client_method(); else { SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_WRONG_SSL_VERSION); diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 66ff3e61e2..a1163ed986 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1044,10 +1044,17 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) protverr = 0; } } else if (s->client_version >= SSL3_VERSION) { + int max_version = TLS_MAX_VERSION; + + if (s->max_proto_version != 0) + max_version = s->max_proto_version; + switch(s->client_version) { default: case TLS1_2_VERSION: - if(!(s->options & SSL_OP_NO_TLSv1_2)) { + if(!(s->options & SSL_OP_NO_TLSv1_2) && + (max_version >= TLS1_2_VERSION) && + (s->min_proto_version <= TLS1_2_VERSION)) { s->version = TLS1_2_VERSION; s->method = TLSv1_2_server_method(); protverr = 0; @@ -1055,7 +1062,9 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) } /* Deliberately fall through */ case TLS1_1_VERSION: - if(!(s->options & SSL_OP_NO_TLSv1_1)) { + if(!(s->options & SSL_OP_NO_TLSv1_1) && + (max_version >= TLS1_1_VERSION) && + (s->min_proto_version <= TLS1_1_VERSION)) { s->version = TLS1_1_VERSION; s->method = TLSv1_1_server_method(); protverr = 0; @@ -1063,7 +1072,9 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) } /* Deliberately fall through */ case TLS1_VERSION: - if(!(s->options & SSL_OP_NO_TLSv1)) { + if(!(s->options & SSL_OP_NO_TLSv1) && + (max_version >= TLS1_VERSION) && + (s->min_proto_version <= TLS1_VERSION)) { s->version = TLS1_VERSION; s->method = TLSv1_server_method(); protverr = 0; @@ -1072,7 +1083,9 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) /* Deliberately fall through */ case SSL3_VERSION: #ifndef OPENSSL_NO_SSL3 - if(!(s->options & SSL_OP_NO_SSLv3)) { + if(!(s->options & SSL_OP_NO_SSLv3) && + (max_version >= SSL3_VERSION) && + (s->min_proto_version <= SSL3_VERSION)) { s->version = SSL3_VERSION; s->method = SSLv3_server_method(); protverr = 0; @@ -1254,8 +1267,18 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) } if (s->method->version == DTLS_ANY_VERSION) { /* Select version to use */ - if (s->client_version <= DTLS1_2_VERSION && - !(s->options & SSL_OP_NO_DTLSv1_2)) { + 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_VERSION_GE(s->client_version, DTLS1_2_VERSION) && + !(s->options & SSL_OP_NO_DTLSv1_2) && + DTLS_VERSION_GE(max_version, DTLS1_2_VERSION) && + DTLS_VERSION_LE(min_version, DTLS1_2_VERSION)) { s->version = DTLS1_2_VERSION; s->method = DTLSv1_2_server_method(); } else if (tls1_suiteb(s)) { @@ -1264,8 +1287,10 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) s->version = s->client_version; al = SSL_AD_PROTOCOL_VERSION; goto f_err; - } else if (s->client_version <= DTLS1_VERSION && - !(s->options & SSL_OP_NO_DTLSv1)) { + } else if (DTLS_VERSION_GE(s->client_version, DTLS1_VERSION) && + !(s->options & SSL_OP_NO_DTLSv1) && + DTLS_VERSION_GE(max_version, DTLS1_VERSION) && + DTLS_VERSION_LE(min_version, DTLS1_VERSION)) { s->version = DTLS1_VERSION; s->method = DTLSv1_server_method(); } else { |