Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSL_CTX_set_ssl_version() preserves TLS 1.3 ciphersuites #7226

Closed
kaduk opened this issue Sep 14, 2018 · 13 comments
Closed

SSL_CTX_set_ssl_version() preserves TLS 1.3 ciphersuites #7226

kaduk opened this issue Sep 14, 2018 · 13 comments
Milestone

Comments

@kaduk
Copy link
Contributor

kaduk commented Sep 14, 2018

SSL_CTX_set_ssl_version() is intended to adapt an SSL_CTX to a new (presumably, fixed-version) SSL_METHOD, filtering down the cipher list to ciphers that are supported by the new method. However, there is no TLS 1.3-specific method, so for any fixed-version method, no TLS 1.3 ciphers should apply. The current implementation of this function just blindly preserves the TLS 1.3 ciphers in the resulting (combined) cipher list, which does not seem like the correct behavior.
This is an issue and not a pull request because I'm not sure if we need to handle the case of
SSL_CTX_set_ssl_version(., TLS_method()).

@agnosticdev
Copy link
Contributor

It looks like the TLS 1.3 specific cipher list is attempted to be used first if possible when ssl_create_cipher_list() is called. However if that is not possible the result cipherstack values are used instead.

// ssl/ssl_ciph.c
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(...) {

    ...

    /*
     * Allocate new "cipherstack" for the result, return with error
     * if we cannot get one.
     */
    if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) {
        OPENSSL_free(co_list);
        return NULL;
    }

    /* Add TLSv1.3 ciphers first - we always prefer those if possible */
    for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++) {
        if (!sk_SSL_CIPHER_push(cipherstack,
                                sk_SSL_CIPHER_value(tls13_ciphersuites, i))) {
            sk_SSL_CIPHER_free(cipherstack);
            return NULL;
        }
    }

    /*
     * The cipher selection for the list is done. The ciphers are added
     * to the resulting precedence to the STACK_OF(SSL_CIPHER).
     */
    for (curr = head; curr != NULL; curr = curr->next) {
        if (curr->active) {
            if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher)) {
                OPENSSL_free(co_list);
                sk_SSL_CIPHER_free(cipherstack);
                return NULL;
            }
#ifdef CIPHER_DEBUG
            fprintf(stderr, "<%s>\n", curr->cipher->name);
#endif
        }
    }
    OPENSSL_free(co_list);      /* Not needed any longer */

    ...
}

@kaduk
Copy link
Contributor Author

kaduk commented Sep 17, 2018

It's not "instead"; the other ciphers are added after the TLS 1.3 ciphers.

But that's not really the question I was trying to ask about, which is more about whether setting the SSL_METHOD back to the TLS_method() is supposed to be a supported operation. If not, then we can just put an empty stack of TLS 1.3 ciphers in place and not worry about it.
I was hoping that @mattcaswell or maybe @t-j-h would have some additional perspective here.

@agnosticdev
Copy link
Contributor

@kaduk yes, I see what you are saying now. Thank you for the clarification. It does look like the TLS 1.3 ciphers are added no matter the method, but I will defer to the tagged maintainers that you mentioned on this behavior.

@t-j-h
Copy link
Member

t-j-h commented Sep 18, 2018

SSL_CTX_set_ssl_version(., TLS_method());
should be a perfectly normal operation to be able to use.
And SSL_CTX_set_ssl_version preserves the currently set tls13 ciphersuites so I would expect it to continue to operate correctly.

I don't think I'm following what you are trying to achieve here specifically.

@kaduk
Copy link
Contributor Author

kaduk commented Sep 18, 2018

I claim that the following set of operations has "unusual and surprising" behavior due to our TLS 1.3-specific implementation:

SSSL_CTX_ *c = SSL_CTX_new(TLS_method());
SSL_CTX_set_ciphersuites(c, "TLS_CHACHA20_POLY1305_SHA256");
SSL_CTX_set_ssl_version(c, TLS1_2_method());
SSL_CTX_set_sssl_version(c, TLS_method());

in that instead of getting the default ciphers for the TLS_method() we only get chacha/poly for the TLS 1.3 ciphers. (The non-TLS-1.3 ciphers do contain the entire list of default ciphers, if I understand the code correctly.)

@t-j-h
Copy link
Member

t-j-h commented Sep 18, 2018

I would expect the ciphersuite list to remain the same before and after the SSL_CTX_set_ssl_version call as conceptually the cipher suite settings are against the SSL_CTX not against the SSL_METHOD.

@t-j-h
Copy link
Member

t-j-h commented Sep 18, 2018

And checking the actual behaviour - it is precisely that - changing the method does not alter the output from SSL_get_ciphers after each method change; and you do see a difference depending on the version-specific method for SSL_get1_supported_ciphers exactly as I would have expected.

@agnosticdev
Copy link
Contributor

Would this be an appropriate case for a unit test, @t-j-h?

@t-j-h
Copy link
Member

t-j-h commented Sep 18, 2018

I'm trying to figure out the point @kaduk is trying to make that I'm not following before I get a sense of whether or not there is some unexpected behaviour or anything that would suggest another test case would be useful.

@kaduk
Copy link
Contributor Author

kaduk commented Sep 18, 2018

The historical behavior of SSL_CTX_set_ssl_version() is to restore the default cipher list for that version, e.g.:

bkaduk:~/git/openssl$ cat ../ciph2.c
#include "openssl/ssl.h"
#include "openssl/safestack.h"

int main(void)
{
    SSL_CTX *ctx;
    STACK_OF(SSL_CIPHER) *ciph;

    ctx = SSL_CTX_new(TLSv1_2_method());
    ciph = SSL_CTX_get_ciphers(ctx);
    printf("stock TLS_method() first (non-TLS1.3) cipher is: %s\n",
        SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciph, 3)));
    SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-SHA256");
    ciph = SSL_CTX_get_ciphers(ctx);
    printf("after SSL_CTX_set_cipher_list() first (non-TLS1.3) cipher is: %s\n",
        SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciph, 3)));
    SSL_CTX_set_ssl_version(ctx, TLSv1_2_method());
    ciph = SSL_CTX_get_ciphers(ctx);
    printf("after SSL_CTX_set_ssl_version() first (non-TLS1.3) cipher is: %s\n",
        SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciph, 3)));
    return 0;
}
bkaduk:~/git/openssl$ LD_LIBRARY_PATH=. ./ciph2
stock TLS_method() first (non-TLS1.3) cipher is: ECDHE-ECDSA-AES256-GCM-SHA384
after SSL_CTX_set_cipher_list() first (non-TLS1.3) cipher is: ECDHE-RSA-AES128-SHA256
after SSL_CTX_set_ssl_version() first (non-TLS1.3) cipher is: ECDHE-ECDSA-AES256-GCM-SHA384

But the behavior for TLS 1.3 cipher suites is different from this historical pattern; they are not reset by SSL_CTX_set_ssl_version():

bkaduk:~/git/openssl$ cat ../ciph.c
#include "openssl/ssl.h"
#include "openssl/safestack.h"

int main(void)
{
    SSL_CTX *ctx;
    STACK_OF(SSL_CIPHER) *ciph;

    ctx = SSL_CTX_new(TLS_method());
    ciph = SSL_CTX_get_ciphers(ctx);
    printf("stock TLS_method() first cipher is: %s\n",
        SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciph, 0)));
    SSL_CTX_set_ciphersuites(ctx, "TLS_CHACHA20_POLY1305_SHA256");
    ciph = SSL_CTX_get_ciphers(ctx);
    printf("after SSL_CTX_set_ciphersuites() first cipher is: %s\n",
        SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciph, 0)));
    SSL_CTX_set_ssl_version(ctx, TLS_method());
    ciph = SSL_CTX_get_ciphers(ctx);
    printf("after SSL_CTX_set_ssl_version() first cipher is: %s\n",
        SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciph, 0)));
    return 0;
}
bkaduk:~/git/openssl$ LD_LIBRARY_PATH=. ./ciph
stock TLS_method() first cipher is: TLS_AES_256_GCM_SHA384
after SSL_CTX_set_ciphersuites() first cipher is: TLS_CHACHA20_POLY1305_SHA256
after SSL_CTX_set_ssl_version() first cipher is: TLS_CHACHA20_POLY1305_SHA256

Whether or not this behavior of SSL_CTX_set_ssl_version() (or even its existence) is a good idea, I think we are supposed to keep the behavior "consistent", and as far as I can tell from pattern analysis, the "rule of behavior" that we are keeping consistent is that this function restores the configured ciphers to the default values for the library.

kaduk added a commit to kaduk/openssl that referenced this issue Sep 19, 2018
Historically SSL_CTX_set_ssl_version() has reset the cipher list
to the default.  Splitting TLS 1.3 ciphers to be tracked separately
caused a behavior change, in that TLS 1.3 cipher configuration was
preserved across calls to SSL_CTX_set_ssl_version().  To restore commensurate
behavior with the historical behavior, set the ciphersuites to the default as
well as setting the cipher list to the default.

Closes: openssl#7226
@mattcaswell
Copy link
Member

The concept of changing the method associated with an SSL_CTX after it has been created is just horrible. I'm also not sure why anyone would want to do that. Really once an SSL_CTX has been created an used to create SSL objects we should not be modifying it. So this limits the usefulness of this function to the period between when the SSL_CTX is first created, and when it is first used to create an SSL.

This only really makes sense if using a fixed version method. All of those are now deprecated - so we really ought to deprecate this function too.

That all being said, and on the assumption that we have to live with it, the fix proposed by @kaduk looks ok.

levitte pushed a commit that referenced this issue Sep 19, 2018
Historically SSL_CTX_set_ssl_version() has reset the cipher list
to the default.  Splitting TLS 1.3 ciphers to be tracked separately
caused a behavior change, in that TLS 1.3 cipher configuration was
preserved across calls to SSL_CTX_set_ssl_version().  To restore commensurate
behavior with the historical behavior, set the ciphersuites to the default as
well as setting the cipher list to the default.

Closes: #7226

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from #7270)

(cherry picked from commit 2340ed2)
@t-j-h
Copy link
Member

t-j-h commented Sep 19, 2018

A better way to look at it is to see the differences in handling between ciphersuites and the cipher list. They are different - they don't do the same thing.
So if you print out the full list of ciphers and not just cherry pick a single item you can see the difference in behaviour much more clearly.

After SSL_CTX_set_cipher_list the list is small and the defaults are gone.
After SSL_CTX_set_ciphersuites the list is large as the cipher suites are prepended to the list.

Now I would argue that resetting the cipher list or the cipher suites is actually the wrong thing to be doing in this function - but that is a separate topic - but having a function which has an entirely undocumented side effect (resetting things) should be fixed. Right now you are noting that a non-documented behaviour isn't consistent with a new concept and I think that is because it wasn't documented.

cat ciph3.c
#include "openssl/ssl.h"
#include "openssl/safestack.h"

int main(void)
{
    SSL_CTX *ctx;
    STACK_OF(SSL_CIPHER) *ciph;
    int i;

    printf("--- SSL_CTX_set_cipher_list ---\n");
    ctx = SSL_CTX_new(TLSv1_2_method());
    ciph = SSL_CTX_get_ciphers(ctx);
    printf("stock TLS_method()\n");
    for(i=0;i<sk_SSL_CIPHER_num(ciph);i++)
      printf("%s%s",i!=0?":":"",SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciph, i)));
    printf("\n");
    SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES128-SHA256");
    ciph = SSL_CTX_get_ciphers(ctx);
    printf("after SSL_CTX_set_cipher_list()\n");
    for(i=0;i<sk_SSL_CIPHER_num(ciph);i++)
      printf("%s%s",i!=0?":":"",SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciph, i)));
    printf("\n");
    SSL_CTX_set_ssl_version(ctx, TLSv1_2_method());
    ciph = SSL_CTX_get_ciphers(ctx);
    printf("after SSL_CTX_set_ssl_version()\n");
    for(i=0;i<sk_SSL_CIPHER_num(ciph);i++)
      printf("%s%s",i!=0?":":"",SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciph, i)));
    printf("\n");
    SSL_CTX_free(ctx);

    printf("--- SSL_CTX_set_ciphersuites ---\n");
    ctx = SSL_CTX_new(TLSv1_2_method());
    ciph = SSL_CTX_get_ciphers(ctx);
    printf("stock TLS_method()\n");
    for(i=0;i<sk_SSL_CIPHER_num(ciph);i++)
      printf("%s%s",i!=0?":":"",SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciph, i)));
    printf("\n");
    SSL_CTX_set_ciphersuites(ctx, "TLS_CHACHA20_POLY1305_SHA256");
    ciph = SSL_CTX_get_ciphers(ctx);
    printf("after SSL_CTX_set_ciphersuites()\n");
    for(i=0;i<sk_SSL_CIPHER_num(ciph);i++)
      printf("%s%s",i!=0?":":"",SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciph, i)));
    printf("\n");
    SSL_CTX_set_ssl_version(ctx, TLSv1_2_method());
    ciph = SSL_CTX_get_ciphers(ctx);
    printf("after SSL_CTX_set_ssl_version()\n");
    for(i=0;i<sk_SSL_CIPHER_num(ciph);i++)
      printf("%s%s",i!=0?":":"",SSL_CIPHER_get_name(sk_SSL_CIPHER_value(ciph, i)));
    printf("\n");
    SSL_CTX_free(ctx);

    return 0;
}
./ciph3    
--- SSL_CTX_set_cipher_list ---
stock TLS_method()
TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:RSA-PSK-AES256-GCM-SHA384:DHE-PSK-AES256-GCM-SHA384:RSA-PSK-CHACHA20-POLY1305:DHE-PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:AES256-GCM-SHA384:PSK-AES256-GCM-SHA384:PSK-CHACHA20-POLY1305:RSA-PSK-AES128-GCM-SHA256:DHE-PSK-AES128-GCM-SHA256:AES128-GCM-SHA256:PSK-AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:ECDHE-PSK-AES256-CBC-SHA384:ECDHE-PSK-AES256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:SRP-AES-256-CBC-SHA:RSA-PSK-AES256-CBC-SHA384:DHE-PSK-AES256-CBC-SHA384:RSA-PSK-AES256-CBC-SHA:DHE-PSK-AES256-CBC-SHA:AES256-SHA:PSK-AES256-CBC-SHA384:PSK-AES256-CBC-SHA:ECDHE-PSK-AES128-CBC-SHA256:ECDHE-PSK-AES128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:SRP-AES-128-CBC-SHA:RSA-PSK-AES128-CBC-SHA256:DHE-PSK-AES128-CBC-SHA256:RSA-PSK-AES128-CBC-SHA:DHE-PSK-AES128-CBC-SHA:AES128-SHA:PSK-AES128-CBC-SHA256:PSK-AES128-CBC-SHA
after SSL_CTX_set_cipher_list()
TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES128-SHA256
after SSL_CTX_set_ssl_version()
TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:RSA-PSK-AES256-GCM-SHA384:DHE-PSK-AES256-GCM-SHA384:RSA-PSK-CHACHA20-POLY1305:DHE-PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:AES256-GCM-SHA384:PSK-AES256-GCM-SHA384:PSK-CHACHA20-POLY1305:RSA-PSK-AES128-GCM-SHA256:DHE-PSK-AES128-GCM-SHA256:AES128-GCM-SHA256:PSK-AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:ECDHE-PSK-AES256-CBC-SHA384:ECDHE-PSK-AES256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:SRP-AES-256-CBC-SHA:RSA-PSK-AES256-CBC-SHA384:DHE-PSK-AES256-CBC-SHA384:RSA-PSK-AES256-CBC-SHA:DHE-PSK-AES256-CBC-SHA:AES256-SHA:PSK-AES256-CBC-SHA384:PSK-AES256-CBC-SHA:ECDHE-PSK-AES128-CBC-SHA256:ECDHE-PSK-AES128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:SRP-AES-128-CBC-SHA:RSA-PSK-AES128-CBC-SHA256:DHE-PSK-AES128-CBC-SHA256:RSA-PSK-AES128-CBC-SHA:DHE-PSK-AES128-CBC-SHA:AES128-SHA:PSK-AES128-CBC-SHA256:PSK-AES128-CBC-SHA
--- SSL_CTX_set_ciphersuites ---
stock TLS_method()
TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:RSA-PSK-AES256-GCM-SHA384:DHE-PSK-AES256-GCM-SHA384:RSA-PSK-CHACHA20-POLY1305:DHE-PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:AES256-GCM-SHA384:PSK-AES256-GCM-SHA384:PSK-CHACHA20-POLY1305:RSA-PSK-AES128-GCM-SHA256:DHE-PSK-AES128-GCM-SHA256:AES128-GCM-SHA256:PSK-AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:ECDHE-PSK-AES256-CBC-SHA384:ECDHE-PSK-AES256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:SRP-AES-256-CBC-SHA:RSA-PSK-AES256-CBC-SHA384:DHE-PSK-AES256-CBC-SHA384:RSA-PSK-AES256-CBC-SHA:DHE-PSK-AES256-CBC-SHA:AES256-SHA:PSK-AES256-CBC-SHA384:PSK-AES256-CBC-SHA:ECDHE-PSK-AES128-CBC-SHA256:ECDHE-PSK-AES128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:SRP-AES-128-CBC-SHA:RSA-PSK-AES128-CBC-SHA256:DHE-PSK-AES128-CBC-SHA256:RSA-PSK-AES128-CBC-SHA:DHE-PSK-AES128-CBC-SHA:AES128-SHA:PSK-AES128-CBC-SHA256:PSK-AES128-CBC-SHA
after SSL_CTX_set_ciphersuites()
TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:RSA-PSK-AES256-GCM-SHA384:DHE-PSK-AES256-GCM-SHA384:RSA-PSK-CHACHA20-POLY1305:DHE-PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:AES256-GCM-SHA384:PSK-AES256-GCM-SHA384:PSK-CHACHA20-POLY1305:RSA-PSK-AES128-GCM-SHA256:DHE-PSK-AES128-GCM-SHA256:AES128-GCM-SHA256:PSK-AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:ECDHE-PSK-AES256-CBC-SHA384:ECDHE-PSK-AES256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:SRP-AES-256-CBC-SHA:RSA-PSK-AES256-CBC-SHA384:DHE-PSK-AES256-CBC-SHA384:RSA-PSK-AES256-CBC-SHA:DHE-PSK-AES256-CBC-SHA:AES256-SHA:PSK-AES256-CBC-SHA384:PSK-AES256-CBC-SHA:ECDHE-PSK-AES128-CBC-SHA256:ECDHE-PSK-AES128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:SRP-AES-128-CBC-SHA:RSA-PSK-AES128-CBC-SHA256:DHE-PSK-AES128-CBC-SHA256:RSA-PSK-AES128-CBC-SHA:DHE-PSK-AES128-CBC-SHA:AES128-SHA:PSK-AES128-CBC-SHA256:PSK-AES128-CBC-SHA
after SSL_CTX_set_ssl_version()
TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:RSA-PSK-AES256-GCM-SHA384:DHE-PSK-AES256-GCM-SHA384:RSA-PSK-CHACHA20-POLY1305:DHE-PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:AES256-GCM-SHA384:PSK-AES256-GCM-SHA384:PSK-CHACHA20-POLY1305:RSA-PSK-AES128-GCM-SHA256:DHE-PSK-AES128-GCM-SHA256:AES128-GCM-SHA256:PSK-AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:ECDHE-PSK-AES256-CBC-SHA384:ECDHE-PSK-AES256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:SRP-AES-256-CBC-SHA:RSA-PSK-AES256-CBC-SHA384:DHE-PSK-AES256-CBC-SHA384:RSA-PSK-AES256-CBC-SHA:DHE-PSK-AES256-CBC-SHA:AES256-SHA:PSK-AES256-CBC-SHA384:PSK-AES256-CBC-SHA:ECDHE-PSK-AES128-CBC-SHA256:ECDHE-PSK-AES128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:SRP-AES-128-CBC-SHA:RSA-PSK-AES128-CBC-SHA256:DHE-PSK-AES128-CBC-SHA256:RSA-PSK-AES128-CBC-SHA:DHE-PSK-AES128-CBC-SHA:AES128-SHA:PSK-AES128-CBC-SHA256:PSK-AES128-CBC-SHA

@kaduk
Copy link
Contributor Author

kaduk commented Sep 19, 2018

A better way to look at it is to see the differences in handling between ciphersuites and the cipher list. They are different - they don't do the same thing.
So if you print out the full list of ciphers and not just cherry pick a single item you can see the difference in behaviour much more clearly.

After SSL_CTX_set_cipher_list the list is small and the defaults are gone.
After SSL_CTX_set_ciphersuites the list is large as the cipher suites are prepended to the list.

I would argue that "large" vs. "small" is not quite the best way to look at things, either, as there are different reference points to compare to. There are some 300-odd pre-TLS 1.3 ciphersuites currently defined, and only 5 TLS 1.3 ciphersuites defined (we only have three of them in our default list). Internally, our code is being forced (for some reasonably good reasons) to squash the TLS 1.2 and TLS 1.3 ciphersuites into a single list, but they are conceptually different and non-interchangable. So it's not that the ciphersuites are "prepended to" the list; they are just the first part of the list, when we squash different things into a single container. So I would think of this as "after SSL_CTX_set_cipher_list, we have 3/3 TLS 1.3 and (small/large) TLS 1.2", and "after SSL_CTX_set_ciphersuites, we have 1/3 TLS 1.3 and (large/large) TLS 1.2". The 1/3 and small/large seem commensurate to me, and more meaningful than the squashed-together (3+small)/(large) and (1+large)/large.

Now I would argue that resetting the cipher list or the cipher suites is actually the wrong thing to be doing in this function - but that is a separate topic - but having a function which has an entirely undocumented side effect (resetting things) should be fixed. Right now you are noting that a non-documented behaviour isn't consistent with a new concept and I think that is because it wasn't documented.

I would also argue that it's the wrong thing to be doing, but not very hard, as I'd be arguing that the function shouldn't exist in the first place :)

I'm happy to prepare some documentation (which will note that this function should be considered deprecated, at least in the first cut).

@mspncp mspncp added this to the 1.1.1a milestone Oct 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants