TLS 1.1 ciphers.
This patch adds support for a different cipher list when the connection
is using TLS 1.1. This is intended to support the case where we want to
use AES with >= TLS 1.1 clients but RC4 otherwise because of the BEAST
attack.
diff --git a/ssl/ssl.h b/ssl/ssl.h
index d5b4c0e..6c53642 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -867,6 +867,11 @@
STACK_OF(SSL_CIPHER) *cipher_list;
/* same as above but sorted for lookup */
STACK_OF(SSL_CIPHER) *cipher_list_by_id;
+ /* cipher_list_tls11 is the list of ciphers when TLS 1.1 or greater is
+ * in use. This only applies to server connections as, for clients, the
+ * version number is known at connect time and so the cipher list can
+ * be set then. */
+ STACK_OF(SSL_CIPHER) *cipher_list_tls11;
struct x509_store_st /* X509_STORE */ *cert_store;
LHASH_OF(SSL_SESSION) *sessions;
@@ -2039,6 +2044,7 @@
#endif
int SSL_CTX_set_cipher_list(SSL_CTX *,const char *str);
+int SSL_CTX_set_cipher_list_tls11(SSL_CTX *,const char *str);
SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth);
void SSL_CTX_free(SSL_CTX *);
long SSL_CTX_set_timeout(SSL_CTX *ctx,long t);
@@ -2647,6 +2653,7 @@
#define SSL_F_ssl_parse_serverhello_tlsext 274
#define SSL_F_ssl3_get_channel_id 275
#define SSL_F_ssl3_send_channel_id 276
+#define SSL_F_SSL_CTX_set_cipher_list_tls11 277
#define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS 100
#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 101
#define SSL_R_INVALID_NULL_CMD_NAME 102
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 1dc6b5a..aac6883 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -1268,7 +1268,7 @@
/*
* Return with error if nothing to do.
*/
- if (rule_str == NULL || cipher_list == NULL || cipher_list_by_id == NULL)
+ if (rule_str == NULL || cipher_list == NULL)
return NULL;
#ifndef OPENSSL_NO_EC
if (!check_suiteb_cipher_list(ssl_method, c, &rule_str))
@@ -1430,12 +1430,18 @@
if (*cipher_list != NULL)
sk_SSL_CIPHER_free(*cipher_list);
*cipher_list = cipherstack;
- if (*cipher_list_by_id != NULL)
- sk_SSL_CIPHER_free(*cipher_list_by_id);
- *cipher_list_by_id = tmp_cipher_list;
- (void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp);
+ if (cipher_list_by_id != NULL)
+ {
+ if (*cipher_list_by_id != NULL)
+ sk_SSL_CIPHER_free(*cipher_list_by_id);
+ *cipher_list_by_id = tmp_cipher_list;
+ (void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp);
- sk_SSL_CIPHER_sort(*cipher_list_by_id);
+ sk_SSL_CIPHER_sort(*cipher_list_by_id);
+ }
+ else
+ sk_SSL_CIPHER_free(tmp_cipher_list);
+
return(cipherstack);
}
diff --git a/ssl/ssl_error.c b/ssl/ssl_error.c
index 1c0c93b..9b00411 100644
--- a/ssl/ssl_error.c
+++ b/ssl/ssl_error.c
@@ -21,6 +21,7 @@
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_check_private_key, 0), "SSL_CTX_check_private_key"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_new, 0), "SSL_CTX_new"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_set_cipher_list, 0), "SSL_CTX_set_cipher_list"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_set_cipher_list_tls11, 0), "SSL_CTX_set_cipher_list_tls11"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_set_session_id_context, 0), "SSL_CTX_set_session_id_context"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_set_ssl_version, 0), "SSL_CTX_set_ssl_version"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_PrivateKey, 0), "SSL_CTX_use_PrivateKey"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 85e33e7..8e326de 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1308,18 +1308,26 @@
* preference */
STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s)
{
- if (s != NULL)
+ if (s == NULL)
+ return NULL;
+
+ if (s->cipher_list != NULL)
{
- if (s->cipher_list != NULL)
- {
- return(s->cipher_list);
- }
- else if ((s->ctx != NULL) &&
- (s->ctx->cipher_list != NULL))
- {
- return(s->ctx->cipher_list);
- }
+ return(s->cipher_list);
}
+
+ if (s->version >= TLS1_1_VERSION)
+ {
+ if (s->ctx != NULL && s->ctx->cipher_list_tls11 != NULL)
+ return s->ctx->cipher_list_tls11;
+ }
+
+ if ((s->ctx != NULL) &&
+ (s->ctx->cipher_list != NULL))
+ {
+ return(s->ctx->cipher_list);
+ }
+
return(NULL);
}
@@ -1381,6 +1389,21 @@
return 1;
}
+int SSL_CTX_set_cipher_list_tls11(SSL_CTX *ctx, const char *str)
+ {
+ STACK_OF(SSL_CIPHER) *sk;
+
+ sk = ssl_create_cipher_list(ctx->method, &ctx->cipher_list_tls11, NULL, str, ctx->cert);
+ if (sk == NULL)
+ return 0;
+ else if (sk_SSL_CIPHER_num(sk) == 0)
+ {
+ OPENSSL_PUT_ERROR(SSL, SSL_CTX_set_cipher_list_tls11, SSL_R_NO_CIPHER_MATCH);
+ return 0;
+ }
+ return 1;
+ }
+
/** specify the ciphers to be used by the SSL */
int SSL_set_cipher_list(SSL *s,const char *str)
{
@@ -2125,6 +2148,8 @@
sk_SSL_CIPHER_free(a->cipher_list);
if (a->cipher_list_by_id != NULL)
sk_SSL_CIPHER_free(a->cipher_list_by_id);
+ if (a->cipher_list_tls11 != NULL)
+ sk_SSL_CIPHER_free(a->cipher_list_tls11);
if (a->cert != NULL)
ssl_cert_free(a->cert);
if (a->client_CA != NULL)