]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
key-exchange: Add dynamic parser for additional key exchange methods
authorTobias Brunner <tobias@strongswan.org>
Mon, 4 Nov 2019 16:27:20 +0000 (17:27 +0100)
committerTobias Brunner <tobias@strongswan.org>
Wed, 7 Aug 2024 14:20:18 +0000 (16:20 +0200)
src/libstrongswan/crypto/key_exchange.c
src/libstrongswan/crypto/key_exchange.h
src/libstrongswan/library.c

index 5b011398978a4f748f96645a98dfe7e65f1eaece..b3fb9641febe0b3005044009c5b53f2c80a384bf 100644 (file)
@@ -18,6 +18,9 @@
 
 #include "key_exchange.h"
 
+#include <collections/hashtable.h>
+#include <threading/mutex.h>
+
 ENUM_BEGIN(key_exchange_method_names, KE_NONE, MODP_1024_BIT,
        "KE_NONE",
        "MODP_768",
@@ -475,10 +478,68 @@ static struct {
        },
 };
 
+/**
+ * Proposal tokens for additional key exchanges.
+ */
+static hashtable_t *tokens;
+
+/**
+ * Mutex to safely access cached tokens.
+ */
+static mutex_t *mutex;
+
+/**
+ * Destroy an allocated proposal token.
+ */
+static void token_destroy(proposal_token_t *this)
+{
+       free(this->name);
+       free(this);
+}
+
+/**
+ * Parse ke<1-7>_<method> for additional key exchange methods.
+ */
+static proposal_token_t *additional_key_exchange_parser(const char *algname)
+{
+       proposal_token_t *token;
+       const proposal_token_t *base;
+       u_int num;
+       char prefix[3], alg[256];
+
+       if (!algname || sscanf(algname, "%2s%1u_%255s", &prefix, &num, alg) != 3 ||
+               !strcaseeq(prefix, "ke"))
+       {
+               return NULL;
+       }
+       mutex->lock(mutex);
+       token = tokens->get(tokens, algname);
+       if (token || num < 1 || num > 7)
+       {
+               goto done;
+       }
+       base = lib->proposal->get_token(lib->proposal, alg);
+       if (!base || base->type != KEY_EXCHANGE_METHOD)
+       {
+               goto done;
+       }
+       INIT(token,
+               .name = strdup(algname),
+               .type = ADDITIONAL_KEY_EXCHANGE_1 + num - 1,
+               .algorithm = base->algorithm,
+               .keysize = base->keysize,
+       );
+       tokens->put(tokens, token->name, token);
+
+done:
+       mutex->unlock(mutex);
+       return token;
+}
+
 /*
  * Described in header
  */
-void diffie_hellman_init()
+void key_exchange_init()
 {
        int i;
 
@@ -498,6 +559,20 @@ void diffie_hellman_init()
                        dh_params[i].public.exp_len = dh_params[i].public.prime.len;
                }
        }
+
+       mutex = mutex_create(MUTEX_TYPE_RECURSIVE);
+       tokens = hashtable_create(hashtable_hash_str, hashtable_equals_str, 4);
+       lib->proposal->register_algname_parser(lib->proposal,
+                                                                                  additional_key_exchange_parser);
+}
+
+/*
+ * Described in header
+ */
+void key_exchange_deinit()
+{
+       tokens->destroy_function(tokens, (void*)token_destroy);
+       mutex->destroy(mutex);
 }
 
 /*
index 73bf61f06e001062aeaa2d826d3b037d80b39f36..4aa4e264b2902334bfd185c2291d6416f02f67af 100644 (file)
@@ -178,9 +178,14 @@ struct diffie_hellman_params_t {
 };
 
 /**
- * Initialize diffie hellman parameters during startup.
+ * Initialize DH parameters and KE token parser during startup.
  */
-void diffie_hellman_init();
+void key_exchange_init();
+
+/**
+ * Deinitialize KE token parser during shutdown.
+ */
+void key_exchange_deinit();
 
 /**
  * Get the parameters associated with the specified Diffie-Hellman group.
index c65b38154750f07ce8ebe28ef5359d75ec220d04..1521fb261c161684b2ec89025f445df76f7a3b6e 100644 (file)
@@ -161,6 +161,8 @@ void library_deinit()
        /* make sure the cache is clear before unloading plugins */
        lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
 
+       key_exchange_deinit();
+
        this->public.streams->destroy(this->public.streams);
        this->public.watcher->destroy(this->public.watcher);
        this->public.scheduler->destroy(this->public.scheduler);
@@ -436,7 +438,7 @@ bool library_init(char *settings, const char *namespace)
 #endif /* INTEGRITY_TEST */
        }
 
-       diffie_hellman_init();
+       key_exchange_init();
 
        return !this->init_failed;
 }