Edit

IABSD.fr/src/lib/libssl/ssl_versions.c

Branch :

  • Show log

    Commit

  • Author : jsing
    Date : 2018-11-06 01:40:23
    Hash : a639fc07
    Message : Include TLSv1.3 in version handling code. This is effectively a no-op, since most of the code clamps to the maximum version supported by the TLS method (which are still at TLSv1.2). ok beck@ bluhm@ tb@

  • lib/libssl/ssl_versions.c
  • /* $OpenBSD: ssl_versions.c,v 1.4 2018/11/06 01:40:23 jsing Exp $ */
    /*
     * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
     *
     * Permission to use, copy, modify, and distribute this software for any
     * purpose with or without fee is hereby granted, provided that the above
     * copyright notice and this permission notice appear in all copies.
     *
     * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     */
    
    #include "ssl_locl.h"
    
    static int
    ssl_clamp_version_range(uint16_t *min_ver, uint16_t *max_ver,
        uint16_t clamp_min, uint16_t clamp_max)
    {
    	if (clamp_min > clamp_max || *min_ver > *max_ver)
    		return 0;
    	if (clamp_max < *min_ver || clamp_min > *max_ver)
    		return 0;
    
    	if (*min_ver < clamp_min)
    		*min_ver = clamp_min;
    	if (*max_ver > clamp_max)
    		*max_ver = clamp_max;
    
    	return 1;
    }
    
    int
    ssl_version_set_min(const SSL_METHOD *meth, uint16_t ver, uint16_t max_ver,
        uint16_t *out_ver)
    {
    	uint16_t min_version, max_version;
    
    	if (ver == 0) {
    		*out_ver = meth->internal->min_version;
    		return 1;
    	}
    
    	min_version = ver;
    	max_version = max_ver;
    
    	if (!ssl_clamp_version_range(&min_version, &max_version,
    	    meth->internal->min_version, meth->internal->max_version))
    		return 0;
    
    	*out_ver = min_version;
    	
    	return 1;
    }
    
    int
    ssl_version_set_max(const SSL_METHOD *meth, uint16_t ver, uint16_t min_ver,
        uint16_t *out_ver)
    {
    	uint16_t min_version, max_version;
    
    	if (ver == 0) {
    		*out_ver = meth->internal->max_version;
    		return 1;
    	}
    
    	min_version = min_ver;
    	max_version = ver;
    
    	if (!ssl_clamp_version_range(&min_version, &max_version,
    	    meth->internal->min_version, meth->internal->max_version))
    		return 0;
    
    	*out_ver = max_version;
    	
    	return 1;
    }
    
    int
    ssl_enabled_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver)
    {
    	uint16_t min_version, max_version;
    
    	/*
    	 * The enabled versions have to be a contiguous range, which means we
    	 * cannot enable and disable single versions at our whim, even though
    	 * this is what the OpenSSL flags allow. The historical way this has
    	 * been handled is by making a flag mean that all higher versions
    	 * are disabled, if any version lower than the flag is enabled.
    	 */
    
    	min_version = 0;
    	max_version = TLS1_3_VERSION;
    
    	if ((s->internal->options & SSL_OP_NO_TLSv1) == 0)
    		min_version = TLS1_VERSION;
    	else if ((s->internal->options & SSL_OP_NO_TLSv1_1) == 0)
    		min_version = TLS1_1_VERSION;
    	else if ((s->internal->options & SSL_OP_NO_TLSv1_2) == 0)
    		min_version = TLS1_2_VERSION;
    	else if ((s->internal->options & SSL_OP_NO_TLSv1_3) == 0)
    		min_version = TLS1_3_VERSION;
    
    	if ((s->internal->options & SSL_OP_NO_TLSv1_3) && min_version < TLS1_3_VERSION)
    		max_version = TLS1_2_VERSION;
    	if ((s->internal->options & SSL_OP_NO_TLSv1_2) && min_version < TLS1_2_VERSION)
    		max_version = TLS1_1_VERSION;
    	if ((s->internal->options & SSL_OP_NO_TLSv1_1) && min_version < TLS1_1_VERSION)
    		max_version = TLS1_VERSION;
    	if ((s->internal->options & SSL_OP_NO_TLSv1) && min_version < TLS1_VERSION)
    		max_version = 0;
    
    	/* Everything has been disabled... */
    	if (min_version == 0 || max_version == 0)
    		return 0;
    
    	/* Limit to configured version range. */
    	if (!ssl_clamp_version_range(&min_version, &max_version,
    	    s->internal->min_version, s->internal->max_version))
    		return 0;
    
    	if (min_ver != NULL)
    		*min_ver = min_version;
    	if (max_ver != NULL)
    		*max_ver = max_version;
    
    	return 1;
    }
    
    int
    ssl_supported_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver)
    {
    	uint16_t min_version, max_version;
    
    	/* DTLS cannot currently be disabled... */
    	if (SSL_IS_DTLS(s)) {
    		min_version = max_version = DTLS1_VERSION;
    		goto done;
    	}
    
    	if (!ssl_enabled_version_range(s, &min_version, &max_version))
    		return 0;
    
    	/* Limit to the versions supported by this method. */
    	if (!ssl_clamp_version_range(&min_version, &max_version,
    	    s->method->internal->min_version,
    	    s->method->internal->max_version))
    		return 0;
    
     done:
    	if (min_ver != NULL)
    		*min_ver = min_version;
    	if (max_ver != NULL)
    		*max_ver = max_version;
    
    	return 1;
    }
    
    int
    ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver)
    {
    	uint16_t min_version, max_version, shared_version;
    
    	*max_ver = 0;
    
    	if (SSL_IS_DTLS(s)) {
    		if (peer_ver >= DTLS1_VERSION) {
    			*max_ver = DTLS1_VERSION;
    			return 1;
    		}
    		return 0;
    	}
    
    	if (peer_ver >= TLS1_3_VERSION)
    		shared_version = TLS1_3_VERSION;
    	else if (peer_ver >= TLS1_2_VERSION)
    		shared_version = TLS1_2_VERSION;
    	else if (peer_ver >= TLS1_1_VERSION)
    		shared_version = TLS1_1_VERSION;
    	else if (peer_ver >= TLS1_VERSION)
    		shared_version = TLS1_VERSION;
    	else
    		return 0;
    
    	if (!ssl_supported_version_range(s, &min_version, &max_version))
    		return 0;
    
    	if (shared_version < min_version)
    		return 0;
    
    	if (shared_version > max_version)
    		shared_version = max_version;
    
    	*max_ver = shared_version;
    
    	return 1;
    }
    
    uint16_t
    ssl_max_server_version(SSL *s)
    {
    	uint16_t max_version, min_version = 0;
    
    	if (SSL_IS_DTLS(s))
    		return (DTLS1_VERSION);
    
    	if (!ssl_enabled_version_range(s, &min_version, &max_version))
    		return 0;
    
    	/*
    	 * Limit to the versions supported by this method. The SSL method
    	 * will be changed during version negotiation, as such we want to
    	 * use the SSL method from the context.
    	 */
    	if (!ssl_clamp_version_range(&min_version, &max_version,
    	    s->ctx->method->internal->min_version,
    	    s->ctx->method->internal->max_version))
    		return 0;
    
    	return (max_version);
    }