Build TLS cipher suite list in a generic fashion
authorMartin Willi <martin@revosec.ch>
Fri, 20 Aug 2010 10:10:21 +0000 (12:10 +0200)
committerMartin Willi <martin@revosec.ch>
Fri, 20 Aug 2010 10:11:21 +0000 (12:11 +0200)
src/libtls/tls_crypto.c

index 5668f13..acb732e 100644 (file)
@@ -401,94 +401,71 @@ static suite_algs_t *find_suite(tls_cipher_suite_t suite)
 }
 
 /**
- * Initialize the cipher suite list
+ * Filter a suite list using a transform enumerator
  */
-static void build_cipher_suite_list(private_tls_crypto_t *this)
+static void filter_suite(private_tls_crypto_t *this,
+                                                suite_algs_t suites[], int *count, int offset,
+                                                enumerator_t*(*create_enumerator)(crypto_factory_t*))
 {
-       encryption_algorithm_t encr;
-       integrity_algorithm_t mac;
-       enumerator_t *encrs, *macs;
-       tls_cipher_suite_t supported[64], unique[64];
-       int count = 0, i, j;
+       suite_algs_t current;
+       int i, remaining = 0;
+       enumerator_t *enumerator;
 
-       /* we assume that we support RSA, but no DHE yet */
-       macs = lib->crypto->create_signer_enumerator(lib->crypto);
-       while (macs->enumerate(macs, &mac))
+       memset(&current, 0, sizeof(current));
+       for (i = 0; i < *count; i++)
        {
-               switch (mac)
+               enumerator = create_enumerator(lib->crypto);
+               while (enumerator->enumerate(enumerator, ((char*)&current) + offset))
                {
-                       case AUTH_HMAC_SHA1_160:
-                               supported[count++] = TLS_RSA_WITH_NULL_SHA;
-                               break;
-                       case AUTH_HMAC_SHA2_256_256:
-                               supported[count++] = TLS_RSA_WITH_NULL_SHA256;
-                               break;
-                       case AUTH_HMAC_MD5_128:
-                               supported[count++] = TLS_RSA_WITH_NULL_MD5;
-                               break;
-                       default:
-                               break;
-               }
-               encrs = lib->crypto->create_crypter_enumerator(lib->crypto);
-               while (encrs->enumerate(encrs, &encr))
-               {
-                       switch (encr)
+                       if ((suites[i].encr == ENCR_NULL ||
+                                !current.encr || current.encr == suites[i].encr) &&
+                               (!current.mac  || current.mac  == suites[i].mac) &&
+                               (!current.prf  || current.prf  == suites[i].prf) &&
+                               (!current.hash || current.hash == suites[i].hash))
                        {
-                               case ENCR_AES_CBC:
-                                       switch (mac)
-                                       {
-                                               case AUTH_HMAC_SHA1_160:
-                                                       supported[count++] = TLS_RSA_WITH_AES_128_CBC_SHA;
-                                                       supported[count++] = TLS_RSA_WITH_AES_256_CBC_SHA;
-                                                       break;
-                                               case AUTH_HMAC_SHA2_256_256:
-                                                       supported[count++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
-                                                       supported[count++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
-                                                       break;
-                                               default:
-                                                       break;
-                                       }
-                                       break;
-                               case ENCR_3DES:
-                                       switch (mac)
-                                       {
-                                               case AUTH_HMAC_SHA1_160:
-                                                       supported[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA;
-                                                       break;
-                                               default:
-                                                       break;
-                                       }
-                                       break;
-                               default:
-                                       break;
+                               suites[remaining] = suites[i];
+                               remaining++;
+                               break;
                        }
                }
-               encrs->destroy(encrs);
+               enumerator->destroy(enumerator);
        }
-       macs->destroy(macs);
+       *count = remaining;
+}
+
+/**
+ * Initialize the cipher suite list
+ */
+static void build_cipher_suite_list(private_tls_crypto_t *this)
+{
+       suite_algs_t suites[countof(suite_algs)];
+       int count = countof(suite_algs), i;
 
-       /* remove duplicates */
-       this->suite_count = 0;
+       /* copy all suites */
        for (i = 0; i < count; i++)
        {
-               bool match = FALSE;
-
-               for (j = 0; j < this->suite_count; j++)
-               {
-                       if (supported[i] == unique[j])
-                       {
-                               match = TRUE;
-                               break;
-                       }
-               }
-               if (!match)
-               {
-                       unique[this->suite_count++] = supported[i];
-               }
+               suites[i] = suite_algs[i];
        }
+       /* filter suite list by each algorithm */
+       filter_suite(this, suites, &count, offsetof(suite_algs_t, encr),
+                                lib->crypto->create_crypter_enumerator);
+       filter_suite(this, suites, &count, offsetof(suite_algs_t, mac),
+                                lib->crypto->create_signer_enumerator);
+       filter_suite(this, suites, &count, offsetof(suite_algs_t, prf),
+                                lib->crypto->create_prf_enumerator);
+       filter_suite(this, suites, &count, offsetof(suite_algs_t, hash),
+                                lib->crypto->create_hasher_enumerator);
+
+       DBG2(DBG_CFG, "%d supported TLS cipher suites:", count);
+       for (i = 0; i < count; i++)
+       {
+               DBG2(DBG_CFG, "  %N", tls_cipher_suite_names, suites[i]);
+       }
+
        free(this->suites);
-       this->suites = malloc(sizeof(tls_cipher_suite_t) * this->suite_count);
-       memcpy(this->suites, unique, sizeof(tls_cipher_suite_t) * this->suite_count);
+       this->suite_count = count;
+       this->suites = malloc(sizeof(tls_cipher_suite_t) * count);
+       memcpy(this->suites, suites, sizeof(tls_cipher_suite_t) * this->suite_count);
 }
 
 METHOD(tls_crypto_t, get_cipher_suites, int,