Index: openssl-0.9.7g/ssl/ssl_ciph.c
===================================================================
--- openssl-0.9.7g.orig/ssl/ssl_ciph.c
+++ openssl-0.9.7g/ssl/ssl_ciph.c
@@ -305,9 +305,18 @@ static void ll_append_tail(CIPHER_ORDER
 	*tail=curr;
 	}
 
-static unsigned long ssl_cipher_get_disabled(void)
-	{
+struct disabled_masks { /* This is a kludge no longer needed with OpenSSL 0.9.9,
+			 * where 128-bit and 256-bit algorithms simply will get
+			 * separate bits. */
+	unsigned long mask; /* everything except m256 */
+	unsigned long m256; /* applies to 256-bit algorithms only */
+};
+
+struct disabled_masks ssl_cipher_get_disabled(void)
+{
 	unsigned long mask;
+	unsigned long m256;
+	struct disabled_masks ret;
 
 	mask = SSL_kFZA;
 #ifdef OPENSSL_NO_RSA
@@ -333,17 +342,24 @@ static unsigned long ssl_cipher_get_disa
 	mask |= (ssl_cipher_methods[SSL_ENC_RC2_IDX ] == NULL) ? SSL_RC2 :0;
 	mask |= (ssl_cipher_methods[SSL_ENC_IDEA_IDX] == NULL) ? SSL_IDEA:0;
 	mask |= (ssl_cipher_methods[SSL_ENC_eFZA_IDX] == NULL) ? SSL_eFZA:0;
-	mask |= (ssl_cipher_methods[SSL_ENC_AES128_IDX] == NULL) ? SSL_AES:0;
 
 	mask |= (ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL) ? SSL_MD5 :0;
 	mask |= (ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL) ? SSL_SHA1:0;
 
-	return(mask);
+	/* finally consider algorithms where mask and m256 differ */
+	m256 = mask;
+	mask |= (ssl_cipher_methods[SSL_ENC_AES128_IDX] == NULL) ? SSL_AES:0;
+	m256 |= (ssl_cipher_methods[SSL_ENC_AES256_IDX] == NULL) ? SSL_AES:0;
+
+	ret.mask = mask;
+	ret.m256 = m256;
+	return ret;
 	}
 
 static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
-		int num_of_ciphers, unsigned long mask, CIPHER_ORDER *co_list,
-		CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
+               int num_of_ciphers, unsigned long mask, unsigned long m256,
+               CIPHER_ORDER *co_list, CIPHER_ORDER **head_p,
+               CIPHER_ORDER **tail_p)
 	{
 	int i, co_list_num;
 	SSL_CIPHER *c;
@@ -360,12 +376,13 @@ static void ssl_cipher_collect_ciphers(c
 	for (i = 0; i < num_of_ciphers; i++)
 		{
 		c = ssl_method->get_cipher(i);
+#define IS_MASKED(c) ((c)->algorithms & (((c)->alg_bits == 256) ? m256 : mask))
 		/* drop those that use any of that is not available */
 #ifdef OPENSSL_FIPS
-		if ((c != NULL) && c->valid && !(c->algorithms & mask)
+		if ((c != NULL) && c->valid && !IS_MASKED(c)
 			&& (!FIPS_mode() || (c->algo_strength & SSL_FIPS)))
 #else
-		if ((c != NULL) && c->valid && !(c->algorithms & mask))
+		if ((c != NULL) && c->valid && !IS_MASKED(c))
 #endif
 			{
 			co_list[co_list_num].cipher = c;
@@ -440,7 +457,8 @@ static void ssl_cipher_collect_aliases(S
 	*ca_curr = NULL;	/* end of list */
 	}
 
-static void ssl_cipher_apply_rule(unsigned long algorithms, unsigned long mask,
+static void ssl_cipher_apply_rule(unsigned long cipher_id, unsigned long ssl_version,
+	        unsigned long algorithms, unsigned long mask,
 		unsigned long algo_strength, unsigned long mask_strength,
 		int rule, int strength_bits, CIPHER_ORDER *co_list,
 		CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
@@ -466,11 +484,21 @@ static void ssl_cipher_apply_rule(unsign
 
 		cp = curr->cipher;
 
+		/* If explicit cipher suite, match only that one for its own protocol version.
+		 * Usual selection criteria will be used for similar ciphersuites from other version! */
+
+		if (cipher_id && (cp->algorithms & SSL_SSL_MASK) == ssl_version)
+		{
+			if (cp->id != cipher_id)
+				continue;
+		}
+
+
 		/*
 		 * Selection criteria is either the number of strength_bits
 		 * or the algorithm used.
 		 */
-		if (strength_bits == -1)
+		else if (strength_bits == -1)
 			{
 			ma = mask & cp->algorithms;
 			ma_s = mask_strength & cp->algo_strength;
@@ -583,7 +611,7 @@ static int ssl_cipher_strength_sort(CIPH
 	 */
 	for (i = max_strength_bits; i >= 0; i--)
 		if (number_uses[i] > 0)
-			ssl_cipher_apply_rule(0, 0, 0, 0, CIPHER_ORD, i,
+			ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, CIPHER_ORD, i,
 					co_list, head_p, tail_p);
 
 	OPENSSL_free(number_uses);
@@ -597,6 +625,7 @@ static int ssl_cipher_process_rulestr(co
 	unsigned long algorithms, mask, algo_strength, mask_strength;
 	const char *l, *start, *buf;
 	int j, multi, found, rule, retval, ok, buflen;
+	unsigned long cipher_id = 0, ssl_version = 0;
 	char ch;
 
 	retval = 1;
@@ -686,6 +715,8 @@ static int ssl_cipher_process_rulestr(co
 			 * use strcmp(), because buf is not '\0' terminated.)
 			 */
 			 j = found = 0;
+                         cipher_id = 0;
+                         ssl_version = 0;
 			 while (ca_list[j])
 				{
 				if (!strncmp(buf, ca_list[j]->name, buflen) &&
@@ -704,6 +735,13 @@ static int ssl_cipher_process_rulestr(co
 			mask |= ca_list[j]->mask;
 			algo_strength |= ca_list[j]->algo_strength;
 			mask_strength |= ca_list[j]->mask_strength;
+			/* explicit ciphersuite found */
+			if (ca_list[j]->valid)
+			{
+				cipher_id = ca_list[j]->id;
+				ssl_version = ca_list[j]->algorithms & SSL_SSL_MASK;
+				break;
+			}
 
 			if (!multi) break;
 			}
@@ -729,18 +767,18 @@ static int ssl_cipher_process_rulestr(co
 			 * rest of the command, if any left, until
 			 * end or ':' is found.
 			 */
-			while ((*l != '\0') && ITEM_SEP(*l))
+			while ((*l != '\0') && !ITEM_SEP(*l))
 				l++;
 			}
 		else if (found)
 			{
-			ssl_cipher_apply_rule(algorithms, mask,
+			ssl_cipher_apply_rule(cipher_id, ssl_version, algorithms, mask,
 				algo_strength, mask_strength, rule, -1,
 				co_list, head_p, tail_p);
 			}
 		else
 			{
-			while ((*l != '\0') && ITEM_SEP(*l))
+			while ((*l != '\0') && !ITEM_SEP(*l))
 				l++;
 			}
 		if (*l == '\0') break; /* done */
@@ -756,6 +794,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_
 	{
 	int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
 	unsigned long disabled_mask;
+	unsigned long disabled_m256;
 	STACK_OF(SSL_CIPHER) *cipherstack;
 	const char *rule_p;
 	CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
@@ -777,7 +816,12 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_
 	 * To reduce the work to do we only want to process the compiled
 	 * in algorithms, so we first get the mask of disabled ciphers.
 	 */
-	disabled_mask = ssl_cipher_get_disabled();
+	{
+		struct disabled_masks d;
+		d = ssl_cipher_get_disabled();
+		disabled_mask = d.mask;
+		disabled_m256 = d.m256;
+	}
 
 	/*
 	 * Now we have to collect the available ciphers from the compiled
@@ -796,7 +840,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_
 		}
 
 	ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers, disabled_mask,
-				   co_list, &head, &tail);
+	                           disabled_m256, co_list, &head, &tail);
 
 	/*
 	 * We also need cipher aliases for selecting based on the rule_str.
@@ -816,9 +860,9 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_
 		SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST,ERR_R_MALLOC_FAILURE);
 		return(NULL);	/* Failure */
 		}
-	ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, disabled_mask,
-				   head);
 
+	ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
+			(disabled_mask & disabled_m256), head);
 	/*
 	 * If the rule_string begins with DEFAULT, apply the default rule
 	 * before using the (possibly available) additional rules.
