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_ciph.c b/ssl/ssl_ciph.c
index e8f04d8..a10aa8f 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -218,6 +218,7 @@
 	const SSL_CIPHER *cipher;
 	int active;
 	int dead;
+	int in_group;
 	struct cipher_order_st *next,*prev;
 	} CIPHER_ORDER;
 
@@ -697,6 +698,7 @@
 			co_list[co_list_num].next = NULL;
 			co_list[co_list_num].prev = NULL;
 			co_list[co_list_num].active = 0;
+			co_list[co_list_num].in_group = 0;
 			co_list_num++;
 #ifdef KSSL_DEBUG
 			printf("\t%d: %s %lx %lx %lx\n",i,c->name,c->id,c->algorithm_mkey,c->algorithm_auth);
@@ -808,7 +810,7 @@
                 unsigned long alg_enc, unsigned long alg_mac,
                 unsigned long alg_ssl,
 		unsigned long algo_strength,
-		int rule, int strength_bits,
+		int rule, int strength_bits, int in_group,
 		CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
 	{
 	CIPHER_ORDER *head, *tail, *curr, *curr2, *last;
@@ -816,8 +818,8 @@
 	int reverse = 0;
 
 #ifdef CIPHER_DEBUG
-	printf("Applying rule %d with %08lx/%08lx/%08lx/%08lx/%08lx %08lx (%d)\n",
-		rule, alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength, strength_bits);
+	printf("Applying rule %d with %08lx/%08lx/%08lx/%08lx/%08lx %08lx (%d) in_group:%d\n",
+		rule, alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength, strength_bits, in_group);
 #endif
 
 	if (rule == CIPHER_DEL)
@@ -892,6 +894,7 @@
 				{
 				ll_append_tail(&head, curr, &tail);
 				curr->active = 1;
+				curr->in_group = in_group;
 				}
 			}
 		/* Move the added cipher to this location */
@@ -901,6 +904,7 @@
 			if (curr->active)
 				{
 				ll_append_tail(&head, curr, &tail);
+				curr->in_group = 0;
 				}
 			}
 		else if	(rule == CIPHER_DEL)
@@ -913,6 +917,7 @@
 				 * works in reverse to maintain the order) */
 				ll_append_head(&head, curr, &tail);
 				curr->active = 0;
+				curr->in_group = 0;
 				}
 			}
 		else if (rule == CIPHER_KILL)
@@ -983,7 +988,7 @@
 	 */
 	for (i = max_strength_bits; i >= 0; i--)
 		if (number_uses[i] > 0)
-			ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, head_p, tail_p);
+			ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, 0, head_p, tail_p);
 
 	OPENSSL_free(number_uses);
 	return(1);
@@ -995,7 +1000,8 @@
 	{
 	unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength;
 	const char *l, *buf;
-	int j, multi, found, rule, retval, ok, buflen;
+	int j, multi, found, rule, retval, ok, buflen, in_group = 0,
+	    has_group = 0;
 	unsigned long cipher_id = 0;
 	char ch;
 
@@ -1007,14 +1013,68 @@
 
 		if (ch == '\0')
 			break;		/* done */
-		if (ch == '-')
+		if (in_group)
+			{
+			if (ch == ']')
+				{
+				if (!in_group)
+					{
+					OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_UNEXPECTED_GROUP_CLOSE);
+					retval = found = in_group = 0;
+					break;
+					}
+				if (*tail_p)
+					(*tail_p)->in_group = 0;
+				in_group = 0;
+				l++;
+				continue;
+				}
+			if (ch == '|')
+				{ rule = CIPHER_ADD; l++; continue; }
+			else if (!(ch >= 'a' && ch <= 'z') &&
+				 !(ch >= 'A' && ch <= 'Z') &&
+				 !(ch >= '0' && ch <= '9'))
+				{
+				OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_UNEXPECTED_OPERATOR_IN_GROUP);
+				retval = found = in_group = 0;
+				break;
+				}
+			else
+				rule = CIPHER_ADD;
+			}
+		else if (ch == '-')
 			{ rule = CIPHER_DEL; l++; }
 		else if (ch == '+')
 			{ rule = CIPHER_ORD; l++; }
+		else if (ch == '!' && has_group)
+			{
+			OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
+			retval = found = in_group = 0;
+			break;
+			}
 		else if (ch == '!')
 			{ rule = CIPHER_KILL; l++; }
+		else if (ch == '@' && has_group)
+			{
+			OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
+			retval = found = in_group = 0;
+			break;
+			}
 		else if (ch == '@')
 			{ rule = CIPHER_SPECIAL; l++; }
+		else if (ch == '[')
+			{
+			if (in_group)
+				{
+				OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_NESTED_GROUP);
+				retval = found = in_group = 0;
+				break;
+				}
+			in_group = 1;
+			has_group = 1;
+			l++;
+			continue;
+			}
 		else
 			{ rule = CIPHER_ADD; }
 
@@ -1057,7 +1117,7 @@
 				 * alphanumeric, so we call this an error.
 				 */
 				OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_INVALID_COMMAND);
-				retval = found = 0;
+				retval = found = in_group = 0;
 				l++;
 				break;
 				}
@@ -1224,7 +1284,7 @@
 			{
 			ssl_cipher_apply_rule(cipher_id,
 				alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, algo_strength,
-				rule, -1, head_p, tail_p);
+				rule, -1, in_group, head_p, tail_p);
 			}
 		else
 			{
@@ -1234,6 +1294,12 @@
 		if (*l == '\0') break; /* done */
 		}
 
+	if (in_group)
+		{
+		OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_INVALID_COMMAND);
+		retval = 0;
+		}
+
 	return(retval);
 	}
 #ifndef OPENSSL_NO_EC
@@ -1297,16 +1363,19 @@
 
 
 STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
-		STACK_OF(SSL_CIPHER) **cipher_list,
+		struct ssl_cipher_preference_list_st **cipher_list,
 		STACK_OF(SSL_CIPHER) **cipher_list_by_id,
 		const char *rule_str, CERT *c)
 	{
 	int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
 	unsigned long disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl;
-	STACK_OF(SSL_CIPHER) *cipherstack, *tmp_cipher_list;
+	STACK_OF(SSL_CIPHER) *cipherstack = NULL, *tmp_cipher_list = NULL;
 	const char *rule_p;
 	CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
 	const SSL_CIPHER **ca_list = NULL;
+	unsigned char *in_group_flags = NULL;
+	unsigned int num_in_group_flags = 0;
+	struct ssl_cipher_preference_list_st *pref_list = NULL;
 
 	/*
 	 * Return with error if nothing to do.
@@ -1348,32 +1417,32 @@
 	/* Now arrange all ciphers by preference: */
 
 	/* Everything else being equal, prefer ephemeral ECDH over other key exchange mechanisms */
-	ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail);
-	ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail);
+	ssl_cipher_apply_rule(0, SSL_kEECDH, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head, &tail);
 
 	/* AES is our preferred symmetric cipher */
-	ssl_cipher_apply_rule(0, 0, 0, SSL_AES, 0, 0, 0, CIPHER_ADD, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, 0, 0, SSL_AES, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail);
 
 	/* Temporarily enable everything else for sorting */
-	ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail);
 
 	/* Low priority for MD5 */
-	ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, 0, &head, &tail);
 
 	/* Move anonymous ciphers to the end.  Usually, these will remain disabled.
 	 * (For applications that allow them, they aren't too bad, but we prefer
 	 * authenticated ciphers.) */
-	ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head, &tail);
 
 	/* Move ciphers without forward secrecy to the end */
-	ssl_cipher_apply_rule(0, 0, SSL_aECDH, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
-	/* ssl_cipher_apply_rule(0, 0, SSL_aDH, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); */
-	ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
-	ssl_cipher_apply_rule(0, SSL_kPSK, 0,0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
-	ssl_cipher_apply_rule(0, SSL_kKRB5, 0,0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, 0, SSL_aECDH, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head, &tail);
+	/* ssl_cipher_apply_rule(0, 0, SSL_aDH, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head, &tail); */
+	ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head, &tail);
+	ssl_cipher_apply_rule(0, SSL_kPSK, 0,0, 0, 0, 0, CIPHER_ORD, -1, 0, &head, &tail);
+	ssl_cipher_apply_rule(0, SSL_kKRB5, 0,0, 0, 0, 0, CIPHER_ORD, -1, 0, &head, &tail);
 
 	/* RC4 is sort-of broken -- move the the end */
-	ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, 0, &head, &tail);
 
 	/* Now sort by symmetric encryption strength.  The above ordering remains
 	 * in force within each class */
@@ -1384,7 +1453,7 @@
 		}
 
 	/* Now disable everything (maintaining the ordering!) */
-	ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail);
+	ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head, &tail);
 
 
 	/*
@@ -1429,21 +1498,18 @@
 	OPENSSL_free((void *)ca_list);	/* Not needed anymore */
 
 	if (!ok)
-		{	/* Rule processing failure */
-		OPENSSL_free(co_list);
-		return(NULL);
-		}
+		goto err;
 	
 	/*
 	 * 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);
-		}
+		goto err;
 
+	in_group_flags = OPENSSL_malloc(num_of_ciphers);
+	if (!in_group_flags)
+		goto err;
 	/*
 	 * The cipher selection for the list is done. The ciphers are added
 	 * to the resulting precedence to the STACK_OF(SSL_CIPHER).
@@ -1457,35 +1523,65 @@
 #endif
 			{
 			sk_SSL_CIPHER_push(cipherstack, curr->cipher);
+			in_group_flags[num_in_group_flags++] = curr->in_group;
 #ifdef CIPHER_DEBUG
 			printf("<%s>\n",curr->cipher->name);
 #endif
 			}
 		}
 	OPENSSL_free(co_list);	/* Not needed any longer */
+	co_list = NULL;
 
 	tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack);
 	if (tmp_cipher_list == NULL)
-		{
-		sk_SSL_CIPHER_free(cipherstack);
-		return NULL;
-		}
+		goto err;
+	pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
+	if (!pref_list)
+		goto err;
+	pref_list->ciphers = cipherstack;
+	pref_list->in_group_flags = OPENSSL_malloc(num_in_group_flags);
+	if (!pref_list->in_group_flags)
+		goto err;
+	memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
+	OPENSSL_free(in_group_flags);
+	in_group_flags = NULL;
 	if (*cipher_list != NULL)
-		sk_SSL_CIPHER_free(*cipher_list);
-	*cipher_list = cipherstack;
+		ssl_cipher_preference_list_free(*cipher_list);
+	*cipher_list = pref_list;
+	pref_list = NULL;
+
 	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;
+		tmp_cipher_list = NULL;
 		(void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id,ssl_cipher_ptr_id_cmp);
 
 		sk_SSL_CIPHER_sort(*cipher_list_by_id);
 		}
 	else
+		{
 		sk_SSL_CIPHER_free(tmp_cipher_list);
+		tmp_cipher_list = NULL;
+		}
 
 	return(cipherstack);
+
+err:
+	if (co_list)
+		OPENSSL_free(co_list);
+	if (in_group_flags)
+		OPENSSL_free(in_group_flags);
+	if (cipherstack)
+		sk_SSL_CIPHER_free(cipherstack);
+	if (tmp_cipher_list)
+		sk_SSL_CIPHER_free(tmp_cipher_list);
+	if (pref_list && pref_list->in_group_flags)
+		OPENSSL_free(pref_list->in_group_flags);
+	if (pref_list)
+		OPENSSL_free(pref_list);
+	return NULL;
 	}
 
 char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)