-/*
- * 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->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) {
- /* Determine which DTLS version to use */
- /* If DTLS 1.2 disabled correct the version number */
- if (options & SSL_OP_NO_DTLSv1_2) {
- 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) {
- 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)
- s->method = DTLSv1_2_client_method();
- s->version = DTLS1_2_VERSION;
- }
- }
-
- s->client_version = s->version;
-
- return 1;
-}
-