diff options
author | Benjamin Kaduk <bkaduk@akamai.com> | 2017-01-30 19:20:14 -0600 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2017-02-23 19:40:25 +0100 |
commit | 90134d9806f0191bc0eb0cde2750f0cd68667a6d (patch) | |
tree | 5ce79363107c5328c44aec2010455352d580bd1c /ssl/statem/statem_srvr.c | |
parent | ccb8e6e0b1c536430290a87ba5c87dc072cc5a12 (diff) | |
download | openssl-90134d9806f0191bc0eb0cde2750f0cd68667a6d.zip openssl-90134d9806f0191bc0eb0cde2750f0cd68667a6d.tar.gz openssl-90134d9806f0191bc0eb0cde2750f0cd68667a6d.tar.bz2 |
Refactor SSL_bytes_to_cipher_list()
Split off the portions that mutate the SSL object into a separate
function that the state machine calls, so that the public API can
be a pure function. (It still needs the SSL parameter in order
to determine what SSL_METHOD's get_cipher_by_char() routine to use,
though.)
Instead of returning the stack of ciphers (functionality that was
not used internally), require using the output parameter, and add
a separate output parameter for the SCSVs contained in the supplied
octets, if desired. This lets us move to the standard return value
convention. Also make both output stacks optional parameters.
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2279)
Diffstat (limited to 'ssl/statem/statem_srvr.c')
-rw-r--r-- | ssl/statem/statem_srvr.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 00e69a6..880996b 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1226,6 +1226,7 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) SSL_COMP *comp = NULL; #endif STACK_OF(SSL_CIPHER) *ciphers = NULL; + STACK_OF(SSL_CIPHER) *scsvs = NULL; int protverr; /* |cookie| will only be initialized for DTLS. */ PACKET session_id, compression, extensions, cookie; @@ -1546,11 +1547,44 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt) } } - if (bytes_to_cipher_list(s, &clienthello.ciphersuites, &ciphers, - clienthello.isv2, &al) == NULL) { + if (!ssl_cache_cipherlist(s, &clienthello.ciphersuites, + clienthello.isv2, &al) || + !bytes_to_cipher_list(s, &clienthello.ciphersuites, &ciphers, &scsvs, + clienthello.isv2, &al)) { goto f_err; } + s->s3->send_connection_binding = 0; + /* Check what signalling cipher-suite values were received. */ + if (scsvs != NULL) { + for(i = 0; i < sk_SSL_CIPHER_num(scsvs); i++) { + c = sk_SSL_CIPHER_value(scsvs, i); + if (SSL_CIPHER_get_id(c) == SSL3_CK_SCSV) { + if (s->renegotiate) { + /* SCSV is fatal if renegotiating */ + SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, + SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING); + al = SSL_AD_HANDSHAKE_FAILURE; + goto f_err; + } + s->s3->send_connection_binding = 1; + } else if (SSL_CIPHER_get_id(c) == SSL3_CK_FALLBACK_SCSV && + !ssl_check_version_downgrade(s)) { + /* + * This SCSV indicates that the client previously tried + * a higher version. We should fail if the current version + * is an unexpected downgrade, as that indicates that the first + * connection may have been tampered with in order to trigger + * an insecure downgrade. + */ + SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, + SSL_R_INAPPROPRIATE_FALLBACK); + al = SSL_AD_INAPPROPRIATE_FALLBACK; + goto f_err; + } + } + } + /* If it is a hit, check that the cipher is in the list */ if (s->hit) { j = 0; |