kdf: Implement wrapper for IKEv2 PRFs

This commit is contained in:
Tobias Brunner
2022-04-14 19:02:56 +02:00
parent ad0e94b6ed
commit 0339ce34f6
4 changed files with 72 additions and 18 deletions
+1 -1
View File
@@ -12,6 +12,6 @@ endif
libstrongswan_kdf_la_SOURCES = \ libstrongswan_kdf_la_SOURCES = \
kdf_plugin.h kdf_plugin.c \ kdf_plugin.h kdf_plugin.c \
kdf_prf_plus.h kdf_prf_plus.c kdf_kdf.h kdf_kdf.c
libstrongswan_kdf_la_LDFLAGS = -module -avoid-version libstrongswan_kdf_la_LDFLAGS = -module -avoid-version
@@ -20,7 +20,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#include "kdf_prf_plus.h" #include "kdf_kdf.h"
typedef struct private_kdf_t private_kdf_t; typedef struct private_kdf_t private_kdf_t;
@@ -34,6 +34,11 @@ struct private_kdf_t {
*/ */
kdf_t public; kdf_t public;
/**
* KDF type.
*/
key_derivation_function_t type;
/** /**
* Underlying PRF. * Underlying PRF.
*/ */
@@ -48,16 +53,20 @@ struct private_kdf_t {
METHOD(kdf_t, get_type, key_derivation_function_t, METHOD(kdf_t, get_type, key_derivation_function_t,
private_kdf_t *this) private_kdf_t *this)
{ {
return KDF_PRF_PLUS; return this->type;
} }
METHOD(kdf_t, get_length, size_t, METHOD(kdf_t, get_length, size_t,
private_kdf_t *this) private_kdf_t *this)
{ {
return SIZE_MAX; if (this->type == KDF_PRF_PLUS)
{
return SIZE_MAX;
}
return this->prf->get_block_size(this->prf);
} }
METHOD(kdf_t, get_bytes, bool, METHOD(kdf_t, get_bytes_prf_plus, bool,
private_kdf_t *this, size_t out_len, uint8_t *buffer) private_kdf_t *this, size_t out_len, uint8_t *buffer)
{ {
chunk_t block, previous = chunk_empty; chunk_t block, previous = chunk_empty;
@@ -93,12 +102,27 @@ METHOD(kdf_t, get_bytes, bool,
return success; return success;
} }
METHOD(kdf_t, get_bytes, bool,
private_kdf_t *this, size_t out_len, uint8_t *buffer)
{
if (out_len != get_length(this))
{
return FALSE;
}
return this->prf->get_bytes(this->prf, this->salt, buffer);
}
METHOD(kdf_t, allocate_bytes, bool, METHOD(kdf_t, allocate_bytes, bool,
private_kdf_t *this, size_t out_len, chunk_t *chunk) 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); *chunk = chunk_alloc(out_len);
if (!get_bytes(this, out_len, chunk->ptr)) if (!this->public.get_bytes(&this->public, out_len, chunk->ptr))
{ {
chunk_free(chunk); chunk_free(chunk);
return FALSE; return FALSE;
@@ -112,6 +136,22 @@ METHOD(kdf_t, set_param, bool,
chunk_t chunk; chunk_t chunk;
bool success = FALSE; bool success = FALSE;
if (this->type == KDF_PRF)
{ /* IKEv2 uses the nonces etc., which we receive as SALT, as PRF key and
* the DH secret as salt */
switch (param)
{
case KDF_PARAM_KEY:
param = KDF_PARAM_SALT;
break;
case KDF_PARAM_SALT:
param = KDF_PARAM_KEY;
break;
default:
break;
}
}
switch (param) switch (param)
{ {
case KDF_PARAM_KEY: case KDF_PARAM_KEY:
@@ -139,13 +179,13 @@ METHOD(kdf_t, destroy, void,
/* /*
* Described in header * Described in header
*/ */
kdf_t *kdf_prf_plus_create(key_derivation_function_t algo, va_list args) kdf_t *kdf_kdf_create(key_derivation_function_t algo, va_list args)
{ {
private_kdf_t *this; private_kdf_t *this;
pseudo_random_function_t prf_alg; pseudo_random_function_t prf_alg;
prf_t *prf; prf_t *prf;
if (algo != KDF_PRF_PLUS) if (algo != KDF_PRF && algo != KDF_PRF_PLUS)
{ {
return NULL; return NULL;
} }
@@ -154,8 +194,9 @@ kdf_t *kdf_prf_plus_create(key_derivation_function_t algo, va_list args)
prf = lib->crypto->create_prf(lib->crypto, prf_alg); prf = lib->crypto->create_prf(lib->crypto, prf_alg);
if (!prf) if (!prf)
{ {
DBG1(DBG_LIB, "failed to create %N for prf+", DBG1(DBG_LIB, "failed to create %N for %N",
pseudo_random_function_names, prf_alg); pseudo_random_function_names, prf_alg,
key_derivation_function_names, algo);
return NULL; return NULL;
} }
@@ -168,8 +209,13 @@ kdf_t *kdf_prf_plus_create(key_derivation_function_t algo, va_list args)
.set_param = _set_param, .set_param = _set_param,
.destroy = _destroy, .destroy = _destroy,
}, },
.type = algo,
.prf = prf, .prf = prf,
); );
if (algo == KDF_PRF_PLUS)
{
this->public.get_bytes = _get_bytes_prf_plus;
}
return &this->public; return &this->public;
} }
@@ -21,7 +21,8 @@
*/ */
/** /**
* Implements prf+ as defined in RFC 7296, section 2.13: * Implements a KDF wrapper around PRFs, and prf+ as defined in RFC 7296,
* section 2.13:
* *
* @verbatim * @verbatim
prf+ (K,S) = T1 | T2 | T3 | T4 | ... prf+ (K,S) = T1 | T2 | T3 | T4 | ...
@@ -34,12 +35,12 @@
... ...
* @endverbatim * @endverbatim
* *
* @defgroup kdf_prf_plus kdf_prf_plus * @defgroup kdf_kdf kdf_kdf
* @{ @ingroup kdf_p * @{ @ingroup kdf_p
*/ */
#ifndef KDF_PRF_PLUS_H_ #ifndef KDF_KDF_H_
#define KDF_PRF_PLUS_H_ #define KDF_KDF_H_
#include <crypto/kdfs/kdf.h> #include <crypto/kdfs/kdf.h>
@@ -50,6 +51,6 @@
* @param args pseudo_random_function_t of the underlying PRF * @param args pseudo_random_function_t of the underlying PRF
* @return kdf_t object, NULL if not supported * @return kdf_t object, NULL if not supported
*/ */
kdf_t *kdf_prf_plus_create(key_derivation_function_t algo, va_list args); kdf_t *kdf_kdf_create(key_derivation_function_t algo, va_list args);
#endif /** KDF_PRF_PLUS_H_ @}*/ #endif /** KDF_KDF_H_ @}*/
+9 -2
View File
@@ -21,7 +21,7 @@
*/ */
#include "kdf_plugin.h" #include "kdf_plugin.h"
#include "kdf_prf_plus.h" #include "kdf_kdf.h"
#include <library.h> #include <library.h>
@@ -48,7 +48,14 @@ METHOD(plugin_t, get_features, int,
private_kdf_plugin_t *this, plugin_feature_t *features[]) private_kdf_plugin_t *this, plugin_feature_t *features[])
{ {
static plugin_feature_t f[] = { static plugin_feature_t f[] = {
PLUGIN_REGISTER(KDF, kdf_prf_plus_create), PLUGIN_REGISTER(KDF, kdf_kdf_create),
PLUGIN_PROVIDE(KDF, KDF_PRF),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA1),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA2_256),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA2_384),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA2_512),
PLUGIN_SDEPEND(PRF, PRF_AES128_XCBC),
PLUGIN_SDEPEND(PRF, PRF_AES128_CMAC),
PLUGIN_PROVIDE(KDF, KDF_PRF_PLUS), PLUGIN_PROVIDE(KDF, KDF_PRF_PLUS),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA1), PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA1),
PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA2_256), PLUGIN_SDEPEND(PRF, PRF_HMAC_SHA2_256),