Win32 fixes from stable branch.
[openssl.git] / ssl / ssl_ciph.c
index 051442f381cd0eecca9ae4cbd12048df465a190b..87aa83a314daf76d444a1580bdd9cae8e8657028 100644 (file)
@@ -190,7 +190,7 @@ typedef struct cipher_order_st
        } CIPHER_ORDER;
 
 static const SSL_CIPHER cipher_aliases[]={
-       /* "ALL" must be first; it doesn't include eNULL (must be specifically enabled) */
+       /* "ALL" doesn't include eNULL (must be specifically enabled) */
        {0,SSL_TXT_ALL, 0,SSL_ALL & ~SSL_eNULL, SSL_ALL ,0,0,0,SSL_ALL,SSL_ALL},
        /* "COMPLEMENTOFALL" */
        {0,SSL_TXT_CMPALL,0,SSL_eNULL,0,0,0,0,SSL_ENC_MASK,0},
@@ -583,6 +583,7 @@ static void ssl_cipher_collect_aliases(SSL_CIPHER **ca_list,
        CIPHER_ORDER *ciph_curr;
        SSL_CIPHER **ca_curr;
        int i;
+       unsigned long enabled_mask = ~mask;
 
        /*
         * First, add the real ciphers as already collected
@@ -598,34 +599,46 @@ static void ssl_cipher_collect_aliases(SSL_CIPHER **ca_list,
 
        /*
         * Now we add the available ones from the cipher_aliases[] table.
-        * They represent either an algorithm, that must be
-        * supported (not disabled through 'mask', i.e. all of the
-        * SSL_MKEY_MASK, SSL_AUTH_MASK, .. bits in the alias are set in 'mask')
+        * They represent either one or more algorithms, some of which
+        * in any affected category must be supported (set in enabled_mask),
         * or represent a cipher strength value (will be added in any case because algorithms=0).
         */
        for (i = 0; i < num_of_group_aliases; i++)
                {
                int algorithms = cipher_aliases[i].algorithms;
 
-               if ((i == 0) /* always fetch "ALL" */ ||
-                   !(((SSL_MKEY_MASK & algorithms) && (SSL_MKEY_MASK & mask)
-                      && ((algorithms & SSL_MKEY_MASK & mask) == (SSL_MKEY_MASK & mask))) ||
-                     ((SSL_AUTH_MASK & algorithms) && (SSL_AUTH_MASK & mask)
-                      && ((algorithms & SSL_AUTH_MASK & mask) == (SSL_AUTH_MASK & mask))) ||
-                     ((SSL_ENC_MASK & algorithms) && (SSL_ENC_MASK & mask)
-                      && ((algorithms & SSL_ENC_MASK & mask) == (SSL_ENC_MASK & mask))) ||
-                     ((SSL_MAC_MASK & algorithms) && (SSL_MAC_MASK & mask)
-                      && ((algorithms & SSL_MAC_MASK & mask) == (SSL_MAC_MASK & mask)))))
+               if (SSL_MKEY_MASK & algorithms)
                        {
-                       *ca_curr = (SSL_CIPHER *)(cipher_aliases + i);
-                       ca_curr++;
+                       if ((SSL_MKEY_MASK & algorithms & enabled_mask) == 0)
+                               continue;
+                       }
+               
+               if (SSL_AUTH_MASK & algorithms)
+                       {
+                       if ((SSL_AUTH_MASK & algorithms & enabled_mask) == 0)
+                               continue;
+                       }
+               
+               if (SSL_ENC_MASK & algorithms)
+                       {
+                       if ((SSL_ENC_MASK & algorithms & enabled_mask) == 0)
+                               continue;
                        }
+               
+               if (SSL_MAC_MASK & algorithms)
+                       {
+                       if ((SSL_MAC_MASK & algorithms & enabled_mask) == 0)
+                               continue;
+                       }
+               
+               *ca_curr = (SSL_CIPHER *)(cipher_aliases + i);
+               ca_curr++;
                }
 
        *ca_curr = NULL;        /* end of list */
        }
 
-static void ssl_cipher_apply_rule(unsigned long cipher_id,
+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,
@@ -652,9 +665,10 @@ static void ssl_cipher_apply_rule(unsigned long cipher_id,
 
                cp = curr->cipher;
 
-               /* If explicit cipher suite match that one only */
+               /* 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)
+               if (cipher_id && (cp->algorithms & SSL_SSL_MASK) == ssl_version)
                        {
                        if (cp->id != cipher_id)
                                continue;
@@ -776,7 +790,7 @@ static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
         */
        for (i = max_strength_bits; i >= 0; i--)
                if (number_uses[i] > 0)
-                       ssl_cipher_apply_rule(0, 0, 0, 0, 0, CIPHER_ORD, i,
+                       ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, CIPHER_ORD, i,
                                        head_p, tail_p);
 
        OPENSSL_free(number_uses);
@@ -790,7 +804,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
        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;
+       unsigned long cipher_id = 0, ssl_version = 0;
        char ch;
 
        retval = 1;
@@ -881,6 +895,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
                         */
                         j = found = 0;
                         cipher_id = 0;
+                        ssl_version = 0;
                         while (ca_list[j])
                                {
                                if (!strncmp(buf, ca_list[j]->name, buflen) &&
@@ -895,12 +910,6 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
                        if (!found)
                                break;  /* ignore this entry */
 
-                       if (ca_list[j]->valid)
-                               {
-                               cipher_id = ca_list[j]->id;
-                               break;
-                               }
-
                        /* New algorithms:
                         *  1 - any old restrictions apply outside new mask
                         *  2 - any new restrictions apply outside old mask
@@ -915,6 +924,14 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
                                        (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;
                        }
 
@@ -943,7 +960,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
                        }
                else if (found)
                        {
-                       ssl_cipher_apply_rule(cipher_id, algorithms, mask,
+                       ssl_cipher_apply_rule(cipher_id, ssl_version, algorithms, mask,
                                algo_strength, mask_strength, rule, -1,
                                head_p, tail_p);
                        }