+/**
+ * Purge suites using a given key type
+ */
+static void filter_key_suites(private_tls_crypto_t *this,
+ suite_algs_t suites[], int *count, key_type_t key)
+{
+ int i, remaining = 0;
+
+ DBG2(DBG_TLS, "disabling %N suites, no backend found", key_type_names, key);
+ for (i = 0; i < *count; i++)
+ {
+ if (suites[i].key != key)
+ {
+ suites[remaining] = suites[i];
+ remaining++;
+ }
+ }
+ *count = remaining;
+}
+
+/**
+ * Filter suites by key exchange user config
+ */
+static void filter_key_exchange_config_suites(private_tls_crypto_t *this,
+ suite_algs_t suites[], int *count)
+{
+ enumerator_t *enumerator;
+ int i, remaining = 0;
+ char *token, *config;
+
+ config = lib->settings->get_str(lib->settings, "%s.tls.key_exchange", NULL,
+ lib->ns);
+ if (config)
+ {
+ for (i = 0; i < *count; i++)
+ {
+ enumerator = enumerator_create_token(config, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (strcaseeq(token, "ecdhe-ecdsa") &&
+ diffie_hellman_group_is_ec(suites[i].dh) &&
+ suites[i].key == KEY_ECDSA)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "ecdhe-rsa") &&
+ diffie_hellman_group_is_ec(suites[i].dh) &&
+ suites[i].key == KEY_RSA)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "dhe-rsa") &&
+ !diffie_hellman_group_is_ec(suites[i].dh) &&
+ suites[i].dh != MODP_NONE &&
+ suites[i].key == KEY_RSA)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "rsa") &&
+ suites[i].dh == MODP_NONE &&
+ suites[i].key == KEY_RSA)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ *count = remaining;
+ }
+}
+
+/**
+ * Filter suites by cipher user config
+ */
+static void filter_cipher_config_suites(private_tls_crypto_t *this,
+ suite_algs_t suites[], int *count)
+{
+ enumerator_t *enumerator;
+ int i, remaining = 0;
+ char *token, *config;
+
+ config = lib->settings->get_str(lib->settings, "%s.tls.cipher", NULL,
+ lib->ns);
+ if (config)
+ {
+ for (i = 0; i < *count; i++)
+ {
+ enumerator = enumerator_create_token(config, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (strcaseeq(token, "aes128") &&
+ suites[i].encr == ENCR_AES_CBC &&
+ suites[i].encr_size == 16)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "aes256") &&
+ suites[i].encr == ENCR_AES_CBC &&
+ suites[i].encr_size == 32)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "aes128gcm") &&
+ suites[i].encr == ENCR_AES_GCM_ICV16 &&
+ suites[i].encr_size == 16)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "aes256gcm") &&
+ suites[i].encr == ENCR_AES_GCM_ICV16 &&
+ suites[i].encr_size == 32)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "camellia128") &&
+ suites[i].encr == ENCR_CAMELLIA_CBC &&
+ suites[i].encr_size == 16)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "camellia256") &&
+ suites[i].encr == ENCR_CAMELLIA_CBC &&
+ suites[i].encr_size == 32)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "3des") &&
+ suites[i].encr == ENCR_3DES)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "null") &&
+ suites[i].encr == ENCR_NULL)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ *count = remaining;
+ }
+}
+
+/**
+ * Filter suites by mac user config
+ */
+static void filter_mac_config_suites(private_tls_crypto_t *this,
+ suite_algs_t suites[], int *count)
+{
+ enumerator_t *enumerator;
+ int i, remaining = 0;
+ char *token, *config;
+
+ config = lib->settings->get_str(lib->settings, "%s.tls.mac", NULL,
+ lib->ns);
+ if (config)
+ {
+ for (i = 0; i < *count; i++)
+ {
+ enumerator = enumerator_create_token(config, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (strcaseeq(token, "md5") &&
+ suites[i].mac == AUTH_HMAC_MD5_128)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "sha1") &&
+ suites[i].mac == AUTH_HMAC_SHA1_160)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "sha256") &&
+ suites[i].mac == AUTH_HMAC_SHA2_256_256)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ if (strcaseeq(token, "sha384") &&
+ suites[i].mac == AUTH_HMAC_SHA2_384_384)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ *count = remaining;
+ }
+}
+
+/**
+ * Filter for specific suites specified in strongswan.conf
+ */
+static void filter_specific_config_suites(private_tls_crypto_t *this,
+ suite_algs_t suites[], int *count)
+{
+ enumerator_t *enumerator;
+ int i, remaining = 0, suite;
+ char *token, *config;
+
+ config = lib->settings->get_str(lib->settings, "%s.tls.suites", NULL,
+ lib->ns);
+ if (config)
+ {
+ for (i = 0; i < *count; i++)
+ {
+ enumerator = enumerator_create_token(config, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ if (enum_from_name(tls_cipher_suite_names, token, &suite) &&
+ suite == suites[i].suite)
+ {
+ suites[remaining++] = suites[i];
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ *count = remaining;
+ }
+}
+
+/**
+ * Filter out unsupported suites on given suite array
+ */
+static void filter_unsupported_suites(suite_algs_t suites[], int *count)
+{
+ /* filter suite list by each algorithm */
+ filter_suite(suites, count, offsetof(suite_algs_t, encr),
+ lib->crypto->create_crypter_enumerator);
+ filter_suite(suites, count, offsetof(suite_algs_t, encr),
+ lib->crypto->create_aead_enumerator);
+ filter_suite(suites, count, offsetof(suite_algs_t, mac),
+ lib->crypto->create_signer_enumerator);
+ filter_suite(suites, count, offsetof(suite_algs_t, prf),
+ lib->crypto->create_prf_enumerator);
+ filter_suite(suites, count, offsetof(suite_algs_t, hash),
+ lib->crypto->create_hasher_enumerator);
+ filter_suite(suites, count, offsetof(suite_algs_t, dh),
+ lib->crypto->create_dh_enumerator);
+}
+