From 9e228de60af5702be492f8c27c389c2d77eaa43e Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 11 Feb 2022 14:49:49 +0100 Subject: [PATCH] kdf: Add plugin that provides a default prf+ implementation --- configure.ac | 4 + src/libstrongswan/Android.mk | 2 + src/libstrongswan/Makefile.am | 7 + src/libstrongswan/plugins/kdf/Makefile.am | 17 +++ src/libstrongswan/plugins/kdf/kdf_plugin.c | 88 +++++++++++ src/libstrongswan/plugins/kdf/kdf_plugin.h | 49 ++++++ src/libstrongswan/plugins/kdf/kdf_prf_plus.c | 150 +++++++++++++++++++ src/libstrongswan/plugins/kdf/kdf_prf_plus.h | 55 +++++++ 8 files changed, 372 insertions(+) create mode 100644 src/libstrongswan/plugins/kdf/Makefile.am create mode 100644 src/libstrongswan/plugins/kdf/kdf_plugin.c create mode 100644 src/libstrongswan/plugins/kdf/kdf_plugin.h create mode 100644 src/libstrongswan/plugins/kdf/kdf_prf_plus.c create mode 100644 src/libstrongswan/plugins/kdf/kdf_prf_plus.h diff --git a/configure.ac b/configure.ac index 86e50a3660..04a1c5ce32 100644 --- a/configure.ac +++ b/configure.ac @@ -148,6 +148,7 @@ ARG_ENABL_SET([gcrypt], [enables the libgcrypt plugin.]) ARG_DISBL_SET([gmp], [disable GNU MP (libgmp) based crypto implementation plugin.]) ARG_DISBL_SET([curve25519], [disable Curve25519 Diffie-Hellman plugin.]) ARG_DISBL_SET([hmac], [disable HMAC crypto implementation plugin.]) +ARG_DISBL_SET([kdf], [disable KDF (prf+) implementation plugin.]) ARG_ENABL_SET([md4], [enable MD4 software implementation plugin.]) ARG_DISBL_SET([md5], [disable MD5 software implementation plugin.]) ARG_ENABL_SET([mgf1], [enable the MGF1 software implementation plugin.]) @@ -1502,6 +1503,7 @@ ADD_PLUGIN([chapoly], [s charon scripts nm cmd]) ADD_PLUGIN([xcbc], [s charon nm cmd]) ADD_PLUGIN([cmac], [s charon nm cmd]) ADD_PLUGIN([hmac], [s charon pki scripts nm cmd]) +ADD_PLUGIN([kdf], [s charon pki scripts nm cmd]) ADD_PLUGIN([ctr], [s charon scripts nm cmd]) ADD_PLUGIN([ccm], [s charon scripts nm cmd]) ADD_PLUGIN([gcm], [s charon scripts nm cmd]) @@ -1656,6 +1658,7 @@ AM_CONDITIONAL(USE_DNSKEY, test x$dnskey = xtrue) AM_CONDITIONAL(USE_SSHKEY, test x$sshkey = xtrue) AM_CONDITIONAL(USE_PEM, test x$pem = xtrue) AM_CONDITIONAL(USE_HMAC, test x$hmac = xtrue) +AM_CONDITIONAL(USE_KDF, test x$kdf = xtrue) AM_CONDITIONAL(USE_CMAC, test x$cmac = xtrue) AM_CONDITIONAL(USE_XCBC, test x$xcbc = xtrue) AM_CONDITIONAL(USE_MYSQL, test x$mysql = xtrue) @@ -1921,6 +1924,7 @@ AC_CONFIG_FILES([ src/libstrongswan/plugins/random/Makefile src/libstrongswan/plugins/nonce/Makefile src/libstrongswan/plugins/hmac/Makefile + src/libstrongswan/plugins/kdf/Makefile src/libstrongswan/plugins/xcbc/Makefile src/libstrongswan/plugins/x509/Makefile src/libstrongswan/plugins/revocation/Makefile diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk index fa9f2b2448..515fd8f76b 100644 --- a/src/libstrongswan/Android.mk +++ b/src/libstrongswan/Android.mk @@ -92,6 +92,8 @@ endif LOCAL_SRC_FILES += $(call add_plugin, hmac) +LOCAL_SRC_FILES += $(call add_plugin, kdf) + LOCAL_SRC_FILES += $(call add_plugin, md4) LOCAL_SRC_FILES += $(call add_plugin, md5) diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index 791b2bcff8..81e841381f 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -395,6 +395,13 @@ if MONOLITHIC endif endif +if USE_KDF + SUBDIRS += plugins/kdf +if MONOLITHIC + libstrongswan_la_LIBADD += plugins/kdf/libstrongswan-kdf.la +endif +endif + if USE_CMAC SUBDIRS += plugins/cmac if MONOLITHIC diff --git a/src/libstrongswan/plugins/kdf/Makefile.am b/src/libstrongswan/plugins/kdf/Makefile.am new file mode 100644 index 0000000000..2488b57fcd --- /dev/null +++ b/src/libstrongswan/plugins/kdf/Makefile.am @@ -0,0 +1,17 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-kdf.la +else +plugin_LTLIBRARIES = libstrongswan-kdf.la +endif + +libstrongswan_kdf_la_SOURCES = \ + kdf_plugin.h kdf_plugin.c \ + kdf_prf_plus.h kdf_prf_plus.c + +libstrongswan_kdf_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/kdf/kdf_plugin.c b/src/libstrongswan/plugins/kdf/kdf_plugin.c new file mode 100644 index 0000000000..d9248a7301 --- /dev/null +++ b/src/libstrongswan/plugins/kdf/kdf_plugin.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2022 Tobias Brunner, codelabs GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "kdf_plugin.h" +#include "kdf_prf_plus.h" + +#include + +typedef struct private_kdf_plugin_t private_kdf_plugin_t; + +/** + * Private data + */ +struct private_kdf_plugin_t { + + /** + * Public interface + */ + kdf_plugin_t public; +}; + +METHOD(plugin_t, get_name, char*, + private_kdf_plugin_t *this) +{ + return "kdf"; +} + +METHOD(plugin_t, get_features, int, + private_kdf_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_REGISTER(KDF, kdf_prf_plus_create), + PLUGIN_PROVIDE(KDF, KDF_PRF_PLUS), + 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), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_kdf_plugin_t *this) +{ + free(this); +} + +/* + * Described in header + */ +plugin_t *kdf_plugin_create() +{ + private_kdf_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + ); + + return &this->public.plugin; +} diff --git a/src/libstrongswan/plugins/kdf/kdf_plugin.h b/src/libstrongswan/plugins/kdf/kdf_plugin.h new file mode 100644 index 0000000000..e6f6cd87eb --- /dev/null +++ b/src/libstrongswan/plugins/kdf/kdf_plugin.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022 Tobias Brunner, codelabs GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup kdf_p kdf + * @ingroup plugins + * + * @defgroup kdf_plugin kdf_plugin + * @{ @ingroup kdf_p + */ + +#ifndef KDF_PLUGIN_H_ +#define KDF_PLUGIN_H_ + +#include + +typedef struct kdf_plugin_t kdf_plugin_t; + +/** + * Plugin implementing the key derivation functions (KDF) in software. + */ +struct kdf_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** KDF_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/kdf/kdf_prf_plus.c b/src/libstrongswan/plugins/kdf/kdf_prf_plus.c new file mode 100644 index 0000000000..f21dcf2391 --- /dev/null +++ b/src/libstrongswan/plugins/kdf/kdf_prf_plus.c @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2022 Tobias Brunner, codelabs GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "kdf_prf_plus.h" + +#include + +typedef struct private_kdf_t private_kdf_t; + +/** + * Private data. + */ +struct private_kdf_t { + + /** + * Public interface. + */ + kdf_t public; + + /** + * Underlying PRF. + */ + prf_t *prf; + + /** + * Salt value. + */ + chunk_t salt; +}; + +METHOD(kdf_t, get_type, key_derivation_function_t, + private_kdf_t *this) +{ + return KDF_PRF_PLUS; +} + +METHOD(kdf_t, get_bytes, bool, + private_kdf_t *this, size_t out_len, uint8_t *buffer) +{ + prf_plus_t *prf_plus; + bool success; + + prf_plus = prf_plus_create(this->prf, TRUE, this->salt); + if (!prf_plus) + { + return FALSE; + } + success = prf_plus->get_bytes(prf_plus, out_len, buffer); + prf_plus->destroy(prf_plus); + return success; +} + +METHOD(kdf_t, allocate_bytes, bool, + private_kdf_t *this, size_t out_len, chunk_t *chunk) +{ + *chunk = chunk_alloc(out_len); + + if (!get_bytes(this, out_len, chunk->ptr)) + { + chunk_free(chunk); + return FALSE; + } + return TRUE; +} + +METHOD(kdf_t, set_param, bool, + private_kdf_t *this, kdf_param_t param, ...) +{ + chunk_t chunk; + bool success = FALSE; + + switch (param) + { + case KDF_PARAM_KEY: + VA_ARGS_GET(param, chunk); + success = this->prf->set_key(this->prf, chunk); + break; + case KDF_PARAM_SALT: + VA_ARGS_GET(param, chunk); + chunk_clear(&this->salt); + this->salt = chunk_clone(chunk); + success = TRUE; + break; + } + return success; +} + +METHOD(kdf_t, destroy, void, + private_kdf_t *this) +{ + this->prf->destroy(this->prf); + chunk_clear(&this->salt); + free(this); +} + +/* + * Described in header + */ +kdf_t *kdf_prf_plus_create(key_derivation_function_t algo, va_list args) +{ + private_kdf_t *this; + pseudo_random_function_t prf_alg; + prf_t *prf; + + if (algo != KDF_PRF_PLUS) + { + return NULL; + } + + VA_ARGS_VGET(args, prf_alg); + prf = lib->crypto->create_prf(lib->crypto, prf_alg); + if (!prf) + { + DBG1(DBG_LIB, "failed to create %N for prf+", + pseudo_random_function_names, prf_alg); + return NULL; + } + + INIT(this, + .public = { + .get_type = _get_type, + .get_bytes = _get_bytes, + .allocate_bytes = _allocate_bytes, + .set_param = _set_param, + .destroy = _destroy, + }, + .prf = prf, + ); + + return &this->public; +} diff --git a/src/libstrongswan/plugins/kdf/kdf_prf_plus.h b/src/libstrongswan/plugins/kdf/kdf_prf_plus.h new file mode 100644 index 0000000000..897f1af601 --- /dev/null +++ b/src/libstrongswan/plugins/kdf/kdf_prf_plus.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022 Tobias Brunner, codelabs GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Implements prf+ as defined in RFC 7296, section 2.13: + * + * @verbatim + prf+ (K,S) = T1 | T2 | T3 | T4 | ... + + where: + T1 = prf (K, S | 0x01) + T2 = prf (K, T1 | S | 0x02) + T3 = prf (K, T2 | S | 0x03) + T4 = prf (K, T3 | S | 0x04) + ... + * @endverbatim + * + * @defgroup kdf_prf_plus kdf_prf_plus + * @{ @ingroup kdf_p + */ + +#ifndef KDF_PRF_PLUS_H_ +#define KDF_PRF_PLUS_H_ + +#include + +/** + * Create a kdf_t object + * + * @param algo KDF_PRF_PLUS + * @param args pseudo_random_function_t of the underlying PRF + * @return kdf_t object, NULL if not supported + */ +kdf_t *kdf_prf_plus_create(key_derivation_function_t algo, va_list args); + +#endif /** KDF_PRF_PLUS_H_ @}*/ -- 2.47.2