]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
botan: Implement HMAC-based IKEv2 PRFs via Botan's HKDF implementation
authorTobias Brunner <tobias@strongswan.org>
Tue, 15 Mar 2022 08:34:10 +0000 (09:34 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 14 Apr 2022 17:02:56 +0000 (19:02 +0200)
src/libstrongswan/plugins/botan/botan_kdf.c
src/libstrongswan/plugins/botan/botan_plugin.c

index b7eeb20e45c7c03eb6c99b50c8271929a3929062..dd2e1e2b4d7a8d1e07dba8b28437a49f76a9ab7a 100644 (file)
@@ -42,6 +42,11 @@ struct private_kdf_t {
         */
        kdf_t public;
 
+       /**
+        * KDF type.
+        */
+       key_derivation_function_t type;
+
        /**
         * Name of the KDF algorithm in Botan.
         */
@@ -57,29 +62,42 @@ struct private_kdf_t {
         */
        chunk_t salt;
 
-#if BOTAN_VERSION_MAJOR == 2
        /**
-        * Used for a manual length check in get_bytes().
+        * Length of the hash output.
         */
        size_t hash_size;
-#endif
 };
 
 METHOD(kdf_t, get_type, key_derivation_function_t,
        private_kdf_t *this)
 {
-       return KDF_PRF_PLUS;
+       return this->type;
 }
 
 METHOD(kdf_t, get_length, size_t,
        private_kdf_t *this)
 {
-       return SIZE_MAX;
+       if (this->type == KDF_PRF_PLUS)
+       {
+               return SIZE_MAX;
+       }
+       return this->hash_size;
 }
 
 METHOD(kdf_t, get_bytes, bool,
        private_kdf_t *this, size_t out_len, uint8_t *buffer)
 {
+       if (this->type == KDF_PRF)
+       {
+               if (out_len != get_length(this) ||
+                       botan_kdf(this->name, buffer, out_len, this->key.ptr, this->key.len,
+                                         this->salt.ptr, this->salt.len, NULL, 0))
+               {
+                       return FALSE;
+               }
+               return TRUE;
+       }
+
 #if BOTAN_VERSION_MAJOR == 2
        /* Botan 2 doesn't check the length, just silently prevents wrapping the
         * counter and returns truncated output, so do this manually */
@@ -99,6 +117,11 @@ METHOD(kdf_t, get_bytes, bool,
 METHOD(kdf_t, allocate_bytes, bool,
        private_kdf_t *this, size_t out_len, chunk_t *chunk)
 {
+       if (this->type == KDF_PRF)
+       {
+               out_len = out_len ?: get_length(this);
+       }
+
        *chunk = chunk_alloc(out_len);
 
        if (!get_bytes(this, out_len, chunk->ptr))
@@ -147,9 +170,9 @@ kdf_t *botan_kdf_create(key_derivation_function_t algo, va_list args)
        private_kdf_t *this;
        pseudo_random_function_t prf_alg;
        const char *hash_name;
-       char *name, buf[8];
+       char *name, buf[HASH_SIZE_SHA512];
 
-       if (algo != KDF_PRF_PLUS)
+       if (algo != KDF_PRF && algo != KDF_PRF_PLUS)
        {
                return NULL;
        }
@@ -160,7 +183,14 @@ kdf_t *botan_kdf_create(key_derivation_function_t algo, va_list args)
        {
                return NULL;
        }
-       if (asprintf(&name, "HKDF-Expand(%s)", hash_name) <= 0)
+       if (algo == KDF_PRF)
+       {
+               if (asprintf(&name, "HKDF-Extract(%s)", hash_name) <= 0)
+               {
+                       return NULL;
+               }
+       }
+       else if (asprintf(&name, "HKDF-Expand(%s)", hash_name) <= 0)
        {
                return NULL;
        }
@@ -174,14 +204,13 @@ kdf_t *botan_kdf_create(key_derivation_function_t algo, va_list args)
                        .set_param = _set_param,
                        .destroy = _destroy,
                },
+               .type = algo,
                .name = name,
-#if BOTAN_VERSION_MAJOR == 2
                .hash_size = hasher_hash_size(hasher_algorithm_from_prf(prf_alg)),
-#endif
        );
 
        /* test if we can actually use the algorithm */
-       if (!get_bytes(this, sizeof(buf), buf))
+       if (!get_bytes(this, algo == KDF_PRF ? get_length(this) : sizeof(buf), buf))
        {
                destroy(this);
                return NULL;
index d19856ad04c018052a2202355828d8c4d20aa759..370b1e7c0a984a173651a3ff374da8f074e4cc39 100644 (file)
@@ -213,6 +213,7 @@ METHOD(plugin_t, get_features, int,
                /* kdfs */
 #ifdef BOTAN_HAS_HKDF
                PLUGIN_REGISTER(SIGNER, botan_kdf_create),
+                       PLUGIN_PROVIDE(KDF, KDF_PRF),
                        PLUGIN_PROVIDE(KDF, KDF_PRF_PLUS),
 #endif /* BOTAN_HAS_HKDF */