Equal preference cipher groups.

This change implements equal-preference groups of cipher suites. This
allows, for example, a server to prefer one of AES-GCM or ChaCha20
ciphers, but to allow the client to pick which one. When coupled with
clients that will boost AES-GCM in their preferences when AES-NI is
present, this allows us to use AES-GCM when the hardware exists and
ChaCha20 otherwise.
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index c0e463c..46b3953 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -250,9 +250,13 @@
 
 	ctx->method=meth;
 
-	sk=ssl_create_cipher_list(ctx->method,&(ctx->cipher_list),
-		&(ctx->cipher_list_by_id),
-		meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST, ctx->cert);
+	sk=ssl_create_cipher_list(
+		ctx->method, &ctx->cipher_list, &ctx->cipher_list_by_id,
+		meth->version == SSL2_VERSION ?
+			"SSLv2" :
+			SSL_DEFAULT_CIPHER_LIST,
+		ctx->cert);
+
 	if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0))
 		{
 		OPENSSL_PUT_ERROR(SSL, SSL_CTX_set_ssl_version, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
@@ -520,6 +524,71 @@
 	return X509_VERIFY_PARAM_set1(ssl->param, vpm);
 	}
 
+void ssl_cipher_preference_list_free(
+	struct ssl_cipher_preference_list_st *cipher_list)
+	{
+	sk_SSL_CIPHER_free(cipher_list->ciphers);
+	OPENSSL_free(cipher_list->in_group_flags);
+	OPENSSL_free(cipher_list);
+	}
+
+struct ssl_cipher_preference_list_st*
+ssl_cipher_preference_list_dup(
+	struct ssl_cipher_preference_list_st *cipher_list)
+	{
+	struct ssl_cipher_preference_list_st* ret = NULL;
+	size_t n = sk_SSL_CIPHER_num(cipher_list->ciphers);
+
+	ret = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
+	if (!ret)
+		goto err;
+	ret->ciphers = NULL;
+	ret->in_group_flags = NULL;
+	ret->ciphers = sk_SSL_CIPHER_dup(cipher_list->ciphers);
+	if (!ret->ciphers)
+		goto err;
+	ret->in_group_flags = OPENSSL_malloc(n);
+	if (!ret->in_group_flags)
+		goto err;
+	memcpy(ret->in_group_flags, cipher_list->in_group_flags, n);
+	return ret;
+
+err:
+	if (ret->ciphers)
+		sk_SSL_CIPHER_free(ret->ciphers);
+	if (ret)
+		OPENSSL_free(ret);
+	return NULL;
+	}
+
+struct ssl_cipher_preference_list_st*
+ssl_cipher_preference_list_from_ciphers(STACK_OF(SSL_CIPHER) *ciphers)
+	{
+	struct ssl_cipher_preference_list_st* ret = NULL;
+	size_t n = sk_SSL_CIPHER_num(ciphers);
+
+	ret = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
+	if (!ret)
+		goto err;
+	ret->ciphers = NULL;
+	ret->in_group_flags = NULL;
+	ret->ciphers = sk_SSL_CIPHER_dup(ciphers);
+	if (!ret->ciphers)
+		goto err;
+	ret->in_group_flags = OPENSSL_malloc(n);
+	if (!ret->in_group_flags)
+		goto err;
+	memset(ret->in_group_flags, 0, n);
+	return ret;
+
+err:
+	if (ret->ciphers)
+		sk_SSL_CIPHER_free(ret->ciphers);
+	if (ret)
+		OPENSSL_free(ret);
+	return NULL;
+	}
+
 X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx)
 	{
 	return ctx->param;
@@ -578,7 +647,8 @@
 	if (s->init_buf != NULL) BUF_MEM_free(s->init_buf);
 
 	/* add extra stuff */
-	if (s->cipher_list != NULL) sk_SSL_CIPHER_free(s->cipher_list);
+	if (s->cipher_list != NULL)
+		ssl_cipher_preference_list_free(s->cipher_list);
 	if (s->cipher_list_by_id != NULL) sk_SSL_CIPHER_free(s->cipher_list_by_id);
 
 	/* Make the next call work :-) */
@@ -1313,19 +1383,19 @@
 
 	if (s->cipher_list != NULL)
 		{
-		return(s->cipher_list);
+		return(s->cipher_list->ciphers);
 		}
 
 	if (s->version >= TLS1_1_VERSION)
 		{
 		if (s->ctx != NULL && s->ctx->cipher_list_tls11 != NULL)
-			return s->ctx->cipher_list_tls11;
+			return s->ctx->cipher_list_tls11->ciphers;
 		}
 
 	if ((s->ctx != NULL) &&
 		(s->ctx->cipher_list != NULL))
 		{
-		return(s->ctx->cipher_list);
+		return(s->ctx->cipher_list->ciphers);
 		}
 
 	return(NULL);
@@ -1981,7 +2051,7 @@
 		&ret->cipher_list,&ret->cipher_list_by_id,
 		meth->version == SSL2_VERSION ? "SSLv2" : SSL_DEFAULT_CIPHER_LIST, ret->cert);
 	if (ret->cipher_list == NULL
-	    || sk_SSL_CIPHER_num(ret->cipher_list) <= 0)
+	    || sk_SSL_CIPHER_num(ret->cipher_list->ciphers) <= 0)
 		{
 		OPENSSL_PUT_ERROR(SSL, SSL_CTX_new, SSL_R_LIBRARY_HAS_NO_CIPHERS);
 		goto err2;
@@ -2145,11 +2215,11 @@
 	if (a->cert_store != NULL)
 		X509_STORE_free(a->cert_store);
 	if (a->cipher_list != NULL)
-		sk_SSL_CIPHER_free(a->cipher_list);
+		ssl_cipher_preference_list_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);
+		ssl_cipher_preference_list_free(a->cipher_list_tls11);
 	if (a->cert != NULL)
 		ssl_cert_free(a->cert);
 	if (a->client_CA != NULL)